📄 nasl_packet_forgery.c
字号:
/* Nessus Attack Scripting Language * * Copyright (C) 2002 - 2004 Tenable Network Security * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, * as published by the Free Software Foundation * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */#include <includes.h>#include <nasl_raw.h>#include "nasl_tree.h"#include "nasl_global_ctxt.h"#include "nasl_func.h"#include "nasl_var.h"#include "nasl_lex_ctxt.h"#include "exec.h"#include "nasl_socket.h"#include "nasl_debug.h"#include "capture_packet.h"#include "strutils.h"#include "nasl_packet_forgery.h"/*--------------[ cksum ]-----------------------------------------*//* * Checksum routine for Internet Protocol family headers (C Version) * From ping examples in W.Richard Stevens "UNIX NETWORK PROGRAMMING" book. */static int np_in_cksum(p,n)u_short *p; int n;{ register u_short answer; register long sum = 0; u_short odd_byte = 0; while( n > 1 ) { sum += *p++; n -= 2; } /* mop up an odd byte, if necessary */ if( n == 1 ) { *(u_char *)(&odd_byte) = *(u_char *)p; sum += odd_byte; } sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ sum += (sum >> 16); /* add carry */ answer = (int)~sum; /* ones-complement, truncate*/ return (answer);}/*--------------[ IP ]--------------------------------------------*/tree_cell* forge_ip_packet(lex_ctxt* lexic){ tree_cell *retc; struct ip *pkt; char *s; struct arglist * script_infos = lexic->script_infos; struct in_addr * dst_addr; char * data; int data_len; dst_addr = plug_get_host_ip(script_infos); if( dst_addr == NULL ) return NULL; data = get_str_local_var_by_name(lexic, "data"); data_len = get_local_var_size_by_name(lexic, "data"); retc = alloc_tree_cell(0, NULL); retc->type = CONST_DATA; retc->size = sizeof(struct ip) + data_len; pkt = (struct ip*)emalloc(sizeof(struct ip) + data_len); retc->x.str_val = (char*)pkt; pkt->ip_hl = get_int_local_var_by_name(lexic, "ip_hl", 5); pkt->ip_v = get_int_local_var_by_name(lexic, "ip_v", 4); pkt->ip_tos = get_int_local_var_by_name(lexic, "ip_tos", 0); /* pkt->ip_len = FIX(get_int_local_var_by_name(lexic, "ip_len", 20 + data_len));*/ pkt->ip_len = FIX(20 + data_len); pkt->ip_id = htons(get_int_local_var_by_name(lexic, "ip_id", rand())); pkt->ip_off = get_int_local_var_by_name(lexic, "ip_off", 0); pkt->ip_off = FIX(pkt->ip_off); pkt->ip_ttl = get_int_local_var_by_name(lexic, "ip_ttl", 64); pkt->ip_p = get_int_local_var_by_name(lexic, "ip_p", 0); pkt->ip_sum = htons(get_int_local_var_by_name(lexic, "ip_sum", 0)); /* source */ s = get_str_local_var_by_name(lexic, "ip_src"); if (s != NULL) inet_aton(s, &pkt->ip_src); /* else this host address? */ /* I know that this feature looks dangerous, but anybody can edit an IP * packet with the string functions */ s = get_str_local_var_by_name(lexic, "ip_dst"); if (s != NULL) inet_aton(s, &pkt->ip_dst); else pkt->ip_dst.s_addr = dst_addr->s_addr; if( data != NULL ) { bcopy(data, retc->x.str_val + sizeof(struct ip), data_len); } if(! pkt->ip_sum) { if(get_int_local_var_by_name(lexic, "ip_sum", -1) < 0) pkt->ip_sum = np_in_cksum((u_short *)pkt, sizeof(struct ip)); } return retc;}tree_cell * get_ip_element(lex_ctxt * lexic){ tree_cell * retc; struct ip * ip = (struct ip*)get_str_local_var_by_name(lexic, "ip"); char * element = get_str_local_var_by_name(lexic, "element"); char ret_ascii[32]; int ret_int = 0; int flag = 0; if( ip == NULL ) { nasl_perror(lexic, "get_ip_element : no valid 'ip' argument!\n"); return NULL; } if( element == NULL) { nasl_perror(lexic, "get_ip_element : no valid 'element' argument!\n"); return NULL; } if(!strcmp(element, "ip_v")) { ret_int = ip->ip_v; flag ++; } else if(!strcmp(element, "ip_id")) { ret_int = UNFIX(ip->ip_id); flag ++ ; } else if(!strcmp(element, "ip_hl")) { ret_int = ip->ip_hl; flag ++; } else if(!strcmp(element, "ip_tos")) { ret_int = ip->ip_tos; flag ++; } else if(!strcmp(element, "ip_len")) { ret_int = UNFIX(ip->ip_len); flag ++; } else if(!strcmp(element, "ip_off")) { ret_int = UNFIX(ip->ip_off); flag ++; } else if(!strcmp(element, "ip_ttl")) { ret_int = ip->ip_ttl; flag ++; } else if(!strcmp(element, "ip_p")) { ret_int = ip->ip_p; flag ++; } else if(!strcmp(element, "ip_sum")) { ret_int = UNFIX(ip->ip_sum); flag ++; } if(flag != 0) { retc = alloc_tree_cell(0, NULL); retc->type = CONST_INT; retc->x.i_val = ret_int; return retc; } if(!strcmp(element, "ip_src")) { snprintf(ret_ascii, sizeof(ret_ascii), "%s", inet_ntoa(ip->ip_src)); flag ++;} else if(!strcmp(element, "ip_dst")){ snprintf(ret_ascii, sizeof(ret_ascii), "%s", inet_ntoa(ip->ip_dst)); flag ++;} if( flag == 0) { printf("%s : unknown element\n", element); return NULL; } retc = alloc_tree_cell(0, NULL); retc->type = CONST_DATA; retc->size = strlen(ret_ascii); retc->x.str_val = estrdup(ret_ascii); return retc;}tree_cell * set_ip_elements(lex_ctxt * lexic){ struct ip * o_pkt = (struct ip*)get_str_local_var_by_name(lexic, "ip"); int size = get_var_size_by_name(lexic, "ip"); tree_cell * retc = alloc_tree_cell(0, NULL); struct ip * pkt; char * s; if(o_pkt == NULL) { nasl_perror(lexic, "set_ip_elements: missing <ip> field\n"); return NULL; } pkt = (struct ip*)emalloc(size); bcopy(o_pkt, pkt, size); pkt->ip_hl = get_int_local_var_by_name(lexic, "ip_hl", pkt->ip_hl); pkt->ip_v = get_int_local_var_by_name(lexic, "ip_v", pkt->ip_v); pkt->ip_tos= get_int_local_var_by_name(lexic, "ip_tos", pkt->ip_tos); pkt->ip_len= FIX(get_int_local_var_by_name(lexic, "ip_len", UNFIX(pkt->ip_len))); pkt->ip_id = htons(get_int_local_var_by_name(lexic, "ip_id", pkt->ip_id)); pkt->ip_off= FIX(get_int_local_var_by_name(lexic, "ip_off", UNFIX(pkt->ip_off))); pkt->ip_ttl= get_int_local_var_by_name(lexic, "ip_ttl", pkt->ip_ttl); pkt->ip_p = get_int_local_var_by_name(lexic, "ip_p", pkt->ip_p); s = get_str_local_var_by_name(lexic, "ip_src"); if (s != NULL) inet_aton(s, &pkt->ip_src); pkt->ip_sum = htons(get_int_local_var_by_name(lexic, "ip_sum", 0)); if(pkt->ip_sum == 0) pkt->ip_sum = np_in_cksum((u_short *)pkt, sizeof(struct ip)); retc->type = CONST_DATA; retc->size = size; retc->x.str_val = (char*)pkt; return retc;}tree_cell * insert_ip_options(lex_ctxt * lexic){ struct ip * ip = (struct ip *)get_str_local_var_by_name(lexic, "ip"); int code = get_int_local_var_by_name(lexic, "code", 0); int len = get_int_local_var_by_name(lexic, "length", 0); char * value = get_str_local_var_by_name(lexic, "value"); int value_size = get_var_size_by_name(lexic, "value"); tree_cell * retc; struct ip * new_packet; char * p; int size = get_var_size_by_name(lexic, "ip"); u_char uc_code, uc_len; int pad_len; char zero = '0'; int i; int hl; if( ip == NULL ) { nasl_perror(lexic, "Usage : insert_ip_options(ip:<ip>, code:<code>, length:<len>, value:<value>\n"); return NULL; } pad_len = 4 - ((sizeof(uc_code) + sizeof(uc_len) + value_size) % 4); if ( pad_len == 4 ) pad_len = 0; hl = ip->ip_hl * 4 < UNFIX(ip->ip_len) ? ip->ip_hl * 4 : UNFIX(ip->ip_len); new_packet = emalloc(size + 4 + value_size + pad_len); bcopy(ip, new_packet, hl); uc_code = (u_char)code; uc_len = (u_char)len; p = (char*)new_packet; bcopy(&uc_code, p+hl,sizeof(uc_code)); bcopy(&uc_len, p+hl+sizeof(uc_code), sizeof(uc_len)); bcopy(value, p+hl+sizeof(uc_code)+sizeof(uc_len), value_size); zero = 0; for(i=0;i<pad_len;i++) { bcopy(&zero, p+hl+sizeof(uc_code)+sizeof(uc_len)+value_size+i, 1); } p = (char*)ip; bcopy(p + hl, new_packet + (sizeof(uc_code) + sizeof(uc_len) + value_size + pad_len) + hl, size - hl); new_packet->ip_hl = (hl + (sizeof(uc_code) + sizeof(uc_len) + value_size + pad_len)) / 4; new_packet->ip_len = FIX(size + sizeof(uc_code) + sizeof(uc_len) + value_size + pad_len); new_packet->ip_sum = 0; new_packet->ip_sum = np_in_cksum((u_short*)new_packet, new_packet->ip_hl*4 > UNFIX(new_packet->ip_len) ? UNFIX(new_packet->ip_len):new_packet->ip_hl*4 ); retc = alloc_tree_cell(0, NULL); retc->type = CONST_DATA; retc->size = size + value_size + sizeof(uc_code) + sizeof(uc_len) + pad_len; retc->x.str_val = (char*)new_packet; return retc;}tree_cell * dump_ip_packet(lex_ctxt * lexic){ int i; for(i=0;;i++) { struct ip * ip = (struct ip*)get_str_var_by_num(lexic, i); if(ip == NULL) break; else { printf("------\n"); printf("\tip_hl : %d\n", ip->ip_hl); printf("\tip_v : %d\n", ip->ip_v); printf("\tip_tos: %d\n", ip->ip_tos); printf("\tip_len: %d\n", UNFIX(ip->ip_len)); printf("\tip_id : %d\n", ntohs(ip->ip_id)); printf("\tip_off: %d\n", UNFIX(ip->ip_off)); printf("\tip_ttl: %d\n", ip->ip_ttl); switch(ip->ip_p) { case IPPROTO_TCP : printf("\tip_p : IPPROTO_TCP (%d)\n", ip->ip_p); break; case IPPROTO_UDP : printf("\tip_p : IPPROTO_UDP (%d)\n", ip->ip_p); break; case IPPROTO_ICMP: printf("\tip_p : IPPROTO_ICMP (%d)\n", ip->ip_p); break; default : printf("\tip_p : %d\n", ip->ip_p); break; } printf("\tip_sum: 0x%x\n", ntohs(ip->ip_sum)); printf("\tip_src: %s\n", inet_ntoa(ip->ip_src)); printf("\tip_dst: %s\n", inet_ntoa(ip->ip_dst)); printf("\n"); } } return FAKE_CELL;}/*--------------[ TCP ]--------------------------------------------*/struct pseudohdr{ struct in_addr saddr; struct in_addr daddr; u_char zero; u_char protocol; u_short length; struct tcphdr tcpheader;};tree_cell* forge_tcp_packet(lex_ctxt* lexic){ tree_cell *retc; char *data; int len; u_char * pkt; struct ip *ip, * tcp_packet; struct tcphdr * tcp; int ipsz; ip = (struct ip*)get_str_local_var_by_name(lexic, "ip"); if (ip == NULL) { nasl_perror(lexic, "forge_tcp_packet : You must supply the 'ip' argument !"); return NULL; } ipsz = get_local_var_size_by_name(lexic, "ip"); if(ipsz > ip->ip_hl * 4) ipsz = ip->ip_hl * 4; data = get_str_local_var_by_name(lexic, "data"); len = data == NULL ? 0 : get_var_size_by_name(lexic, "data"); retc = alloc_tree_cell(0, NULL); retc->type = CONST_DATA; tcp_packet = (struct ip*)emalloc(ipsz + sizeof(struct tcphdr) + len); retc->x.str_val = (char*)tcp_packet; pkt = (u_char*) tcp_packet; bcopy(ip, tcp_packet, ipsz ); /* recompute the ip checksum, because the ip length changed */ if(UNFIX(tcp_packet->ip_len) <= tcp_packet->ip_hl * 4) { if(get_int_local_var_by_name(lexic, "update_ip_len", 1)) { tcp_packet->ip_len = FIX(tcp_packet->ip_hl*4 + sizeof(struct tcphdr) + len); tcp_packet->ip_sum = 0; tcp_packet->ip_sum = np_in_cksum((u_short*)tcp_packet, sizeof(struct ip)); } } tcp = (struct tcphdr *)((char*)tcp_packet + tcp_packet->ip_hl*4); tcp->th_sport = ntohs(get_int_local_var_by_name(lexic, "th_sport", 0)); tcp->th_dport = ntohs(get_int_local_var_by_name(lexic, "th_dport", 0)); tcp->th_seq = htonl(get_int_local_var_by_name(lexic, "th_seq", rand())); tcp->th_ack = htonl(get_int_local_var_by_name(lexic, "th_ack", 0)); tcp->th_x2 = get_int_local_var_by_name(lexic, "th_x2", 0); tcp->th_off = get_int_local_var_by_name(lexic, "th_off", 5); tcp->th_flags = get_int_local_var_by_name(lexic, "th_flags", 0); tcp->th_win = htons(get_int_local_var_by_name(lexic, "th_win", 0)); tcp->th_sum = get_int_local_var_by_name(lexic, "th_sum", 0); tcp->th_urp = get_int_local_var_by_name(lexic, "th_urp", 0); if(data != NULL) bcopy(data, (char*)tcp + sizeof(struct tcphdr), len); if(!tcp->th_sum) { struct pseudohdr pseudoheader; char * tcpsumdata = emalloc(sizeof(struct pseudohdr) + (len % 2 ? len + 1 : len ) ); struct in_addr source, dest; source.s_addr = ip->ip_src.s_addr; dest.s_addr = ip->ip_dst.s_addr; bzero(&pseudoheader, 12+sizeof(struct tcphdr)); pseudoheader.saddr.s_addr=source.s_addr; pseudoheader.daddr.s_addr=dest.s_addr; pseudoheader.protocol=IPPROTO_TCP; pseudoheader.length=htons(sizeof(struct tcphdr)+len); bcopy((char *) tcp,(char *) &pseudoheader.tcpheader,sizeof(struct tcphdr)); /* fill tcpsumdata with data to checksum */ bcopy((char *) &pseudoheader, tcpsumdata ,sizeof(struct pseudohdr)); if( data != NULL ) bcopy((char *) data, tcpsumdata + sizeof(struct pseudohdr), len ); tcp->th_sum = np_in_cksum((unsigned short *)tcpsumdata,12+sizeof(struct tcphdr) + len ); efree(&tcpsumdata ); } retc->size = ipsz + sizeof(struct tcphdr) + len; return retc;}tree_cell * get_tcp_element(lex_ctxt * lexic){ u_char * packet = (u_char*)get_str_local_var_by_name(lexic, "tcp"); struct ip * ip; int ipsz; struct tcphdr * tcp; char * element; int ret; tree_cell * retc; ipsz = get_local_var_size_by_name(lexic, "tcp"); if(packet == NULL) { nasl_perror(lexic, "get_tcp_element : Error ! No valid 'tcp' argument !\n"); return NULL; } ip = (struct ip * )packet; if(ip->ip_hl * 4 > ipsz) return NULL; /* Invalid packet */ if(UNFIX(ip->ip_len) > ipsz) return NULL; /* Invalid packet */ tcp = (struct tcphdr*)(packet + ip->ip_hl * 4); element = get_str_local_var_by_name(lexic, "element"); if(!element) { nasl_perror(lexic, "get_tcp_element : Error ! No valid 'element' argument !\n"); return NULL; } if(!strcmp(element, "th_sport"))ret = ntohs(tcp->th_sport); else if(!strcmp(element, "th_dsport"))ret = ntohs(tcp->th_dport); else if(!strcmp(element, "th_seq"))ret = ntohl(tcp->th_seq); else if(!strcmp(element, "th_ack"))ret = ntohl(tcp->th_ack); else if(!strcmp(element, "th_x2"))ret = tcp->th_x2; else if(!strcmp(element, "th_off"))ret = tcp->th_off; else if(!strcmp(element, "th_flags"))ret = tcp->th_flags; else if(!strcmp(element, "th_win"))ret = ntohs(tcp->th_win); else if(!strcmp(element, "th_sum"))ret = tcp->th_sum; else if(!strcmp(element, "th_urp"))ret = tcp->th_urp; else if(!strcmp(element, "data")){ retc = alloc_tree_cell(0, NULL); retc->type = CONST_DATA; retc->size = UNFIX(ip->ip_len) - ntohl(tcp->th_off) * 4; retc->x.str_val = emalloc(retc->size); bcopy(tcp + ntohl(tcp->th_off) * 4, retc->x.str_val, retc->size); return retc;} else { nasl_perror(lexic, "Unknown tcp field %s\n", element); return NULL; } retc = alloc_tree_cell(0, NULL); retc->type = CONST_INT; retc->x.i_val = ret; return retc;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -