/***************************************************************************
ipsorcery.c - main for console
-------------------
begin : Sun Sep 23 2001
copyright : (C) 2001 by Josiah Zayner
email : phric@legions.org
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "wand.h"
void usage(char *progname)
{
printf("\nUsage: %s [options]\n"
"IP: [-is|-id|-ih|-iv|-il|-it|-io|-id|-ip]\n"
"-is: source host or address def. 127.0.0.1\n"
"-id: source destination or adress def. 127.0.0.1\n"
"-ih: IP header length def. 5\n"
"-iv: IP version def. 4\n"
"-il: Time-to-Live def. 64\n"
"-it: Type-of-Service def. 0\n"
"-io: IP frag offset [(D)on't Fragment|(M)ore Fragments|(F)ragment|(N)one]\n"
"-ii: IP packet ID for fragmentaion def. 0\n"
"-ip: IP protocol [TCP|UDP|ICMP|IP] def. TCP\n"
"-iO: IP options\n"
"TCP: [-ts|-td|-to|-tq|-ta|-tf|-tw|-tu]\n"
"-ts: TCP source port, def. rand()\n"
"-td: TCP destination port def. 80\n"
"-to: TCP data offset of header def. 5\n"
"-tq: TCP sequence number def. rand()\n"
"-ta: TCP ack sequence number def. 0\n"
"-tf: TCP flags [(S)yn|(A)ck|(F)in|(P)ush|(R)st|(U)rg|(N)one] def. S\n"
"-tw: TCP Window Size def. rand()\n"
"-tu: TCP urg pointer def. 0\n"
"UDP: [-us|-ud|-ul]\n"
"-us: UDP source port def. rand()\n"
"-ud: UDP destination port def. 161\n"
"-ul: UDP length\n"
" RIP: [-uR|-uRc|-uRv]\n"
" -uR: Send default RIP packet to port 520\n"
" -uRc: RIP command [RQ|RS|TN|TF|SR|TQ|TS|TA|UQ|US|UA] def. RQ\n"
" For a list of RIP commands run program with -h rip \n"
" -uRv: RIP version [1|2] def. 2\n"
"Note: Entry Tables should be used with response packets[RS|TS|US]\n"
" -uRa(1|2|etc.): RIP Entry table Address exmp. -uRa1 \n"
" -uRn(1|2|etc.): RIP Entry table Netmask, exmp. -uRn2\n"
" -uRh(1|2|etc.): RIP Entry table Next Hop, exmp. -uRn(num)\n"
" -uRm(1|2|etc.): RIP Entry table Metric\n"
" -uRr(1|2|etc.): RIP Entry table Route Tag\n"
" -uRe: Add default RIP entry table to packet\n"
"ICMP: [-ct|-cs]\n"
"-ct: ICMP type def. ECHO REQUEST\n"
"-cs: ICMP sub code def. 0\n"
"-ci: ICMP sequence ID def. 0\n"
"For list of ICMP Types and Subcodes run program with -h icmp.\n"
"IGMP:[-gt|-gc|-ga|-gn]\n"
"-gt: IGMP type [D|L|M|MT|MR|P|R1|R2|R3] def. M\n"
"-gc: IGMP sub code for types P and D def. 0\n"
"-gm: IGMP Max. resp. Time for Queries ie. MR\n"
"-ga: IGMP group address def. 0\n"
"-gn: IGMP no router alert or no internetwork Type-Of-Service [r|i||]\n"
"For list of IGMP Types and Subcodes run program with -h igmp.\n"
"OSPF:[-ov|-ot|-or|-oe|-oa|-ou]\n"
"-ov: OSPF Version\n"
"-ot: OSPF Type[(H)ello|(D)b Desc.|(R)equest|(U)pdate|(A)ck]\n"
"-or: OSPF Router ID\n"
"-oe: OSPF Area ID\n"
"-oa: OSPF Auth Type[(N)one|(P)ass|(C)rypto]\n"
"-ou <data>: OSPF Authentication Data\n"
"-D \"<data>\": for datapayload\n"
"-N <num packets>: send <num packets> number packets \n"
"-S <verbosity>: (v)erbose, (s)hort, (t)urn off packet snoop\n"
"-v: print version \n"
,progname
);
exit(-1);
}
void icmp_info(void)
{
printf("ICMP Types and Subcodes:\n"
"Types:\n"
"Echo Reply 0\n"
"Destination Unreachable 3\n"
" Subcodes:\n"
" Network Unreachable 0\n"
" Host Unreachable 1\n"
" Protocol Unreachable 2\n"
" Port Unreachable 3\n"
" Fragmentation Needed 4\n"
" Source Route Failed 5\n"
" Network Unknown 6\n"
" Host Unknown 7\n"
" Host Isolated 8\n"
" Network Prohibited 9\n"
" Host Prohibited 10\n"
" Bad TOS for Network 11\n"
" Bad TOS for Host 12\n"
" Packet Filtered 13\n"
" Precedence Violation 14\n"
" Precedence Cutoff 15\n\n"
"Source Quench 4\n"
"Redirect 5\n"
" Subcodes:\n"
" Redirect Network 0\n"
" Redirect Host 1\n"
" Redirect Network TOS 2\n"
" Redirect Host TOS 3\n\n"
"Echo Request 8\n"
"Router Advertisement 9\n"
"Router Solicitation 10\n"
"Time Exceeded 11\n"
" Subcodes:\n"
" Time to Live 0\n"
" Frag Reassembly 1\n\n"
"Parameter Problems 12\n"
" Subcode:\n"
" Option Missing 0\n\n"
"Timestamp Request 13\n"
"Timestamp Reply 14\n"
"Information Request 15\n"
"Information Reply 16\n"
"Address Mask Request 17\n"
"Address Mask Reply 18\n"
"Traceroute 30\n"
" Subcodes:\n"
" Successful Forward 0\n"
" No Route 1\n\n"
"Conversion Error 31\n"
"Mobile Host Redirect 32\n"
"IPv6 Where Are You? 33\n"
"IPv6 I am Here 34\n"
"Mobile Reg. Request 35\n"
"Mobile Reg. Reply 36\n"
"Domain Name Request 37\n"
"Domain Name Reply 38\n"
);
exit(0);
}
void igmp_info(void)
{
printf("IGMP Types: [D|L|M|MR|MT|P|R1|R2|R3]\n"
" DVMRP: D\n"
" Subcode:\n"
" Probe: 1\n"
" Report: 2\n"
" Ask Neighbors: 3\n"
" Neighbors: 4\n"
" Ask Neighbors 2: 5\n"
" Neighbors V. 1: 6\n"
" Prune: 7\n"
" Graft: 8\n"
" Graft ACK: 9\n"
" Membership Query: M\n"
" Subcode = Max Response Time\n"
" Membership Report Version 1: R1\n"
" Membership Report Version 2: R2\n"
" Membership Report Version 3: R3\n"
" Member Trace: MT\n"
" Member Response: MR\n"
" Subcode = Max Response Time\n"
" Leave Group: L\n"
" PIM Version 1: P\n"
" Subcode:\n"
" Register: 1\n"
" Register Stop: 2\n"
" Join/Prune: 3\n"
" RP Reachable: 4\n"
" Assert: 5\n"
" Graft: 6\n"
" Graft ACK: 7\n"
" Mode: 8\n"
);
exit(0);
}
void rip_info(void)
{
printf("RIP Commands [RQ|RS|TN|TF|SR|TQ|TS|TA|UQ|US|UA]\n"
" RS: Response Packet\n"
" RQ: Request Packet\n"
" TN: Trace On\n"
" TF: Trace Off\n"
" SR: Sun Reserved\n"
" TQ: Triggered Request\n"
" TR: Triggered Response\n"
" TA: Triggered Acknowledgement\n"
" UQ: Update Request\n"
" UR: Update Response\n"
" UA: Update Acknowledgment\n"
);
exit(0);
}
int main(int argc, char **argv)
{
int d_size = 65535;
static int x = 1, optlen = 0;
static int rip_go = 0, y = 0;
static int *opts;
struct ip *eyep = NULL;
struct tcphdr *tcpea = NULL;
struct udphdr *udpea = NULL;
struct nmrhdr *nmr_magic = NULL;
struct icmp *icmpea = NULL;
struct igmp *igmpea = NULL;
struct rip *rip = NULL;
struct rip_ent rip_e[25];
struct ospf *ohspef = NULL;
struct extra_ingredients ex_in;
struct ip_option ip_option[2];
static char *data = NULL;
char packet[65535];
static int oper;
if(argc <= 1){ usage(argv[0]); } /* if no arguments print usage */
srand(time(NULL)); /* seed current time for random numbers*/
memset(packet, 0, 65535);
memset(&ex_in, '\0', sizeof(struct extra_ingredients));
ex_in.READ_IT = 1; /* initialize our scooby style snooper */
ex_in.num = 1; /* one scooby snack please! */
eyep = (struct ip *)packet; /* point ip header into packet */
/* Everyone of our packets use IP! */
ip_sorcery(eyep,
wherefromto("127.0.0.1"),
wherefromto("127.0.0.1"),
0,
5,
4,
0,
40,
0,
64,
0
);
/* if we got one argument lets parse it*/
if(argc > 1)
{
for(;x < argc; x++)
{
if(argv[x][0] != '-')
{
fprintf(stderr, "Bad Option: %s, see usage -h\n",argv[x]);
}
/* first it checks the first letter to see what protocol
to pick it then initializes the headers and parses any
further options by another function get_<protocol>_arg
*/
switch((int)argv[x][1])
{
case 'i':
d_size = 65535 - S_IP;
optlen = get_ip_arg(argv[x], argv[x + 1], eyep, opts);
x++; /* increment x so we skip the next argument */
break; /* end of IP header arguments */
case 'T':
case 't':
if(eyep->ip_p && eyep->ip_p != 6)
{ fprintf(stderr, "Only one protocol at a time please!\n"); exit(-1); }
/* intialize tcp packet */
if(eyep->ip_p != 6)
{
eyep->ip_p = 6;
d_size = 65535 - (S_IP + sizeof(struct tcphdr));
tcpea = (struct tcphdr *)&packet[S_IP + optlen + S_NMR];
tcpea->th_sport = (u_short)htons(rand() % 3000); /* random source port <= 3000 */
tcpea->th_dport = htons(23);
tcpea->th_off = 5;
tcpea->th_seq = htonl(1+(unsigned long int)(1000000000.0 * rand()/(RAND_MAX+1.0))); /* sequence number */
tcpea->th_ack = 0; /* ack sequence */
tcpea->th_flags = TH_SYN; /* default tcp SYN packet */
tcpea->th_win = htons((rand() % 1024) + 300); /* 300 <= random window size <= 1324 */
tcpea->th_urp = 0;
}
get_tcp_arg(argv[x], argv[x + 1], tcpea);
x++;
break; /* end of TCP header arguments */
case 'u':
if(eyep->ip_p && eyep->ip_p != 17) {
fprintf(stderr, "Only one protocol at a time please!\n"); exit(-1);
}
if(eyep->ip_p != 17)
{
eyep->ip_p = 17;
d_size = 65535 - S_IP + sizeof(struct udphdr); /* max data size */
/* put udp header in place and psuedo no miss routed header */
udpea = (struct udphdr *)&packet[S_IP + optlen + S_NMR];
udpea->uh_sport = htons(rand() % 3000); /* source port */
udpea->uh_dport = htons(20); /* destination port */
udpea->uh_ulen = sizeof(struct udphdr);
}
/* make sure we don't try and get UDP args for RIP */
if(argv[x][2] == 'R')
{
if(!rip_go)
{
/* RIP broadcast */
if(eyep->ip_dst.s_addr == 0x1000007f)
eyep->ip_dst = wherefromto("224.0.0.9");
memset(rip_e, 0, (sizeof(struct rip_ent) * 3));
udpea->uh_sport = htons(520);
udpea->uh_dport = htons(520);
rip = (struct rip *)&packet[S_IP + optlen + S_NMR + S_UDP];
rip->comm = 0x01;
rip->vers = 0x02; /* vers 2 */
rip->none = 0;
rip_go++;
}
get_rip_arg(argv[x],argv[x + 1], rip, rip_e);
}
else { get_udp_arg(argv[x], argv[x + 1], udpea); }
x++;
break; /* end of UDP header arguments */
/* start ICMP arguments */
case 'c':
if(eyep->ip_p && eyep->ip_p != 1)
{ fprintf(stderr, "Only one protocol at a time please!\n"); exit(-1); }
if(argv[x][2] && !argv[x][3])
{
if(argv[x + 1])
{
/* intialize our ICMP header */
if(eyep->ip_p != 1)
{
eyep->ip_p = 1;
d_size = 65535 - (S_IP + S_ICMP);
icmpea = (struct icmp *)&packet[S_IP + optlen];
icmpea->icmp_type = ICMP_ECHO;
icmpea->icmp_code = 0;
}
get_icmp_arg(argv[x], argv[x + 1], icmpea);
}
else { printf("Bad input: %s, for %s\n", argv[x + 1], argv[x]); exit(-1); }
}
else { printf("Bad option: %s\n", argv[x]); exit(-1); }
x++;
break; /* end of ICMP header arguments */
/* start IGMP */
case 'g':
if(eyep->ip_p && eyep->ip_p != 2)
{ fprintf(stderr, "Only one protocol at a time please!\n"); exit(-1); }
if(argv[x][2] && !argv[x][3])
{
/* intialize our IGMP header */
if(eyep->ip_p != 2)
{
eyep->ip_p = 2;
d_size = 65535 - (S_IP + S_IGMP);
eyep->ip_tos = 0xc0; /* internetwork traffic */
/* inet_ntoa("224.0.0.1", &igmpea->group); */
eyep->ip_ttl = 1; /* IGMP ttl needs to always be one */
ip_option[0].opt = htons(0x9404);
ip_option[1].opt = htons(0x0000);
memcpy(&packet[S_IP], &ip_option, sizeof(&ip_option));
optlen = 4;
igmpea = (struct igmp *)&packet[S_IP + optlen];
}
get_igmp_arg(argv[x], argv[x + 1], igmpea);
}
else { printf("Bad option: %s\n", argv[x]); exit(-1); }
x++;
break; /* end of IGMP header arguments */
case 'o':
if(eyep->ip_p != 89)
{
eyep->ip_p = 89;
/* destination AllSPFRouters group */
eyep->ip_dst = wherefromto("224.0.0.6");
ohspef = (struct ospf *)&packet[S_IP + optlen];
ohspef->vers = 0x02;
ohspef->type = 0x01;
ohspef->length = htons(20);
ohspef->area_id = 0;
d_size = 65535 - (S_IP + S_OSPF);
eyep->ip_tos = 0xc0; /* internetwork traffic */
}
get_ospf_arg(argv[x], argv[x + 1], ohspef);
x++;
break; /* end of OSPF header args */
/* get data and make sure it is small enough for one packet
*/
case 'D':
if(argv[x + 1])
{
/* make sure they don't try to stuff in too much data */
if(strlen(argv[x + 1]) > d_size)
{ fprintf(stderr,"Data size too big!\n"); exit(-1); }
data = clalloc(d_size); /* allocate data */
memcpy(data, argv[x + 1], strlen(argv[x + 1]));
d_size = strlen(argv[x + 1]);
}
x++;
break;
/* for fragmentation later! */
case 'F':
eyep->ip_off = htons(0x0002);
break;
case 'N':
if(argv[x + 1])
{
ex_in.num = atoi(argv[x + 1]);
}
x++;
break;
case 'S':
if(argv[x + 1])
{
if(strpbrk(argv[x +1], "vV"))
ex_in.READ_IT = 2;
else if(strpbrk(argv[x +1], "sS"))
ex_in.READ_IT = 1;
else if(strpbrk(argv[x +1], "tT"))
ex_in.READ_IT = 0;
}
x++;
break;
case 'h':
if(!argv[x + 1]){ usage(argv[0]); }
else if(strpbrk(argv[x + 1], "cC")){ icmp_info(); }
else if(strpbrk(argv[x + 1], "gG")){ igmp_info(); }
else if(strpbrk(argv[x + 1], "rR")){ rip_info(); }
break;
case 'v':
printf("IP Sorcery %s\n", _VERSION_);
exit(0);
break;
default:
fprintf(stderr, "Bad Option: %s, see usage -h\n", argv[x]);
exit(-1);
break;
}/* switch argv[x][1] */
} /* for(... */
}/* if(argc > 1) */
if(!data){ d_size = 0; }
if(optlen){
/* optlen = x8bits we need to convert to x32bits
if the options length in bytes (%)modulous 4
returns a remainder we take that remainder and add it to
the options length in bytes divided by 4(optlen /4)
Remember we must pad with NULLs thats why we convert
the remainder to 32 bytes.
ex. 5 bytes * 8bits = 2 * 32bits
4 bytes * 8bits = 1 * 32bits
*/
if(optlen % 4){ oper = (optlen / 4) + (optlen % 4); }
else { oper = (optlen / 4); }
eyep->ip_hl = 5 + oper; /* hl is in x32 bits */
}
/* for psuedo no miss routed packets header */
if(eyep->ip_p == 6 || eyep->ip_p == 17)
{
/* create psuedo header */
nmr_magic = (struct nmrhdr *)&packet[S_IP];
nmr_magic->saddr = eyep->ip_src;
nmr_magic->daddr = eyep->ip_dst;
nmr_magic->none = 0;
nmr_magic->protocol = eyep->ip_p;
}
/* Do we have ICMP YES!! We have a winner */
if(eyep->ip_p == 1)
{
if(d_size) {
memcpy(&packet[S_IP + optlen + S_ICMP], data, d_size);
}
icmpea->icmp_cksum = in_cksum((u_short *)&packet[S_IP + optlen], S_ICMP + d_size);
ex_in.pack_sz = S_IP + optlen + S_ICMP + d_size;
}
else if(eyep->ip_p == 2)
{
if(d_size) {
memcpy(&packet[S_IP + optlen + S_IGMP], data, d_size);
}
igmpea->cksum = in_cksum((u_short *)&packet[S_IP + optlen], S_IGMP + d_size);
ex_in.pack_sz = S_IP + optlen + S_IGMP + d_size;
}
else if(eyep->ip_p == 6)
{
nmr_magic->length = htons(S_TCP + d_size);
if(d_size) {
memcpy(&packet[S_IP + optlen + S_TCP + S_NMR], data, d_size);
}
tcpea->th_sum = in_cksum((u_short *)&packet[S_IP],
S_TCP + S_NMR + d_size
);
/* move the packet to cover up the psuedo header */
memmove(&packet[S_IP], &packet[S_IP + optlen + S_NMR], S_TCP + d_size);
memcpy(&ex_in.dport, &packet[22], sizeof(u_short));
ex_in.pack_sz = S_TCPIP + optlen + d_size;
}
else if(eyep->ip_p == 17)
{
if(rip_go)
{
if(rip_e)
{
/* wow, for the rip entry tables, if a table is specified
one of these three fields will always be non-zero
!!!!!fix address family!!!!!
*/
for(y = 0;(rip_e[y].addr_fam > 0 ||
rip_e[y].route_tag > 0 ||
rip_e[y].metric > 0) && y < 25;
y++
)
{
memcpy(packet + S_IP + optlen + S_NMR +
S_UDP + S_RIP +
(sizeof(struct rip_ent) * y),
&rip_e[y],
sizeof(struct rip_ent)
);
}
memcpy(packet + S_IP + optlen + S_NMR + S_UDP + S_RIP +
(sizeof(struct rip_ent) * y), data, d_size);
d_size = d_size + S_RIP + (sizeof(struct rip_ent) * y);
}
else
{
memcpy(packet + S_IP + optlen + S_NMR + S_UDP + S_RIP, data, d_size);
d_size = d_size + S_RIP;
}
}
nmr_magic->length = htons(S_UDP + d_size);
if(d_size) {
memcpy(&packet[S_IP + optlen + S_UDP + S_NMR], data, d_size);
}
/* calculate checksum */
udpea->uh_sum = in_cksum((u_short *)&packet[S_IP + optlen], S_NMR + S_UDP + d_size);
/* move the packet to cover up the psuedo header */
memmove(&packet[20], &packet[S_IP + optlen + S_NMR], S_UDP + d_size);
ex_in.dport = udpea->uh_dport;
ex_in.pack_sz = S_IP + optlen + S_UDP + d_size;
}
else if(eyep->ip_p == 89)
{
if(d_size) {
memcpy(&packet[S_IP + optlen + S_OSPF], data, d_size);
}
ohspef->cs = in_cksum((u_short *)&packet[S_IP + optlen], S_OSPF +d_size);
ex_in.pack_sz = S_IP + optlen + S_OSPF + d_size;
}
/* finally send out packet */
packet_sorcery(packet,
ex_in,
eyep->ip_dst,
eyep->ip_src
);
/* free our memory */
if(data){ free(data); }
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1