发新话题
打印

[原创]构造RAWPACKET模仿ipconfig /release

[原创]构造RAWPACKET模仿ipconfig /release

文章作者:Eros412
信息来源:邪恶八进制信息安全团队
类型:网络编程
前言:ipconfig.exe 使用IpReleaseAddress()这个函数完成DHCP_RELEASE,以下是模仿整个过程的部分代码
复制内容到剪贴板
代码:
#include<packet32.h>
#include<winsock.h>
#include<Iphlpapi.h>
#include<stdio.h>
#include<windows.h>
#pragma comment(lib,"packet.lib")
#pragma comment(lib,"ws2_32.lib")
#pragma comment(lib,"Iphlpapi.lib")

typedef struct _myparam
{
  char myip[15];//本机ip
  char gatewayip[15];//网关ip
  unsigned char mymac[6];//本机mac
  unsigned char gatewaymac[6];//网关mac

}MYPARAM,*PMYPARAM;

#pragma pack(push,1)

typedef struct _ethdr //14字节的ethernet首部
{
unsigned char eh_dst[6];//目标地址的mac(网关mac)
unsigned char eh_src[6];//源地址的mac(本机mac)
unsigned short eh_type;//类型,本程序的是IP
}ETHERNETHEADER,*PETHERNETHEADER;

typedef struct ip_hdr //20个字节IP首部
{
unsigned char h_verlen;//版本
unsigned char tos;//首部长度
unsigned short total_len;//总长度,ipheader+udpheader+dhcpheader+数据
unsigned short ident;//Identification
unsigned short frag_and_flags;//是否是碎片包
unsigned char ttl; //Time to live
unsigned char proto; //DHCP的protocol是UDP,0x11
unsigned short checksum;//20个字节IP首部的校验和
unsigned int sourceIP;//源地址的IP(本机ip)
unsigned int destIP;//目标地址的IP(网关ip)
}IPHEADER,*PIPHEADER;

typedef struct tsd_hdr//12个字节伪首部
{
unsigned long saddr;//源地址的IP(本机ip)
unsigned long daddr;//目标地址的IP(网关ip)
unsigned char mbz; //0
unsigned char ptcl;//协议
unsigned short tcpl;//psdheader+udpheader+dhcpheader+数据的长度
}PSDHEADER,*PPSDHEADER;

typedef struct udp_hdr //8个字节UDP首部
{
unsigned short sourceport; //源端口 ,DHCP客户端==68
unsigned short destport;//目标端口,DHCP服务端==67
unsigned short udp_length; //udp首部+dhcp首部+数据的长度
unsigned short udp_checksum; //psd首部+udp首部+dhcp首部+数据的校验和
} UDPHEADER,*PUDPHEADER;

typedef struct dhcp_header //240个字节的DHCP首部
{
unsigned char MessageType; //类型,0x01==BOOT_REQUEST,0x02==BOOT_REPLY,
unsigned char HardwareType;//硬件类型 (Ethernet)
unsigned char HardwareAddrLen;//MAC的长度,6
unsigned char Hops;//每经过一个DHCP中继加1
unsigned long TranID;//Transaction ID
unsigned short Secondselaps;//0
unsigned short BootpFlag;//0

DWORD ClientIP;//0
DWORD YourIP;//源地址的IP(本机ip)
DWORD NextServerIP;//0
DWORD RelayAgentIP;//0

unsigned char ClientMac[6];//源地址的mac(本机mac)
unsigned char PAdding[10];//0
unsigned char ServerName[64];//0
unsigned char BootFileName[128];//0

unsigned long MagicCookie;//每个机子有不同的号
}DHCPHEADER, *PDHCPHEADER;

typedef struct dhcp_option
{
unsigned char OptionNum;
unsigned char OptionLen;
}DHCPOPTION, *PDHCPOPTION;

typedef struct dhcp_type//3个字节的类型部分
{
DHCPOPTION option;
unsigned char value;
}DHCPTYPE, *PDHCPTYPE;

typedef struct server_iden//这边用来填写网关的ip地址
{
DHCPOPTION option;
DWORD value;
}SERVERIDEN, *PSERVERIDEN;

typedef struct client_iden/这边用来填写本机的mac
{
DHCPOPTION option;
unsigned char value[7];
unsigned char end;
}CLIENTIDEN, *PCLIENTIDEN;
#pragma pack(pop)

USHORT checksum(USHORT *buffer, int size)//校验和
{
unsigned long cksum=0;
while(size >1)
{
cksum+=*buffer++;//把数据的前两个字节先换位,因为两个UCHAR变一个USHORT,类似htons(),然后加起来,指针向后移,一直加完全部数据
size-=sizeof(USHORT);
}
if(size)//加上最后一个字节
cksum+=*(UCHAR*)buffer;

cksum=(cksum >> 16)+(cksum&0xffff);//高位向左移,加上低位;(cksum >> 16)如果cksum是0x12340000,就变成0x1234;(cksum&0xffff)如果cksum是0x12345678,就变成0x5678
cksum+=(cksum >>16);//cksum再加上高位
return (USHORT)(~cksum);//取反(低位的)
}

//一些定义
#define IP 0x0800
#define BOOT_REQUEST 1
#define ETHERNET 1
#define BROADCAST 0x8000
#define DHCP_MESSAGE_TYPE 53
#define DHCP_REALEASE 7
#define SERVER_ID 54
#define CLIENT_ID 61

void main(){

  MYPARAM myparam;
  unsigned char ipbuf[342]={0};//完整的RAWPACKET == ETHERNET_HEADER+IPHEADER+UDPHEADER+DHCPHEADER+数据
  unsigned char udpchecksum[320]={0};//加 PSDHEADER和UDPHEADER ,计算udpheader的checksum
  unsigned char udpbuf[308]={0};//加 UDPHEADER
  unsigned char mybuf[300]={0};//没有 UDPHEADER
  char classid[50]={0};//通过classid的比较来选定ADAPTER
  char clsid[50]={0};

  IPHEADER ipheader;
  ipheader.h_verlen=(4<<4 | sizeof(IPHEADER)/sizeof(DWORD));//4<<4 ,BINARY 100向左移4位,变成1000000,原本的0x04变成0x40。sizeof(IPHEADER)/sizeof(DWORD),sizeof(DWORD)==4,20/4==5。所以0x40|0x05==0x45
  ipheader.tos=0;
  ipheader.total_len=htons(sizeof(IPHEADER)+sizeof(udpbuf));
  ipheader.ident=htons(11670);
  ipheader.frag_and_flags=0;//不是碎片包
  ipheader.ttl=128;//最大为255,0xFF
  ipheader.proto=IPPROTO_UDP;
  ipheader.checksum=0;//计算校验和时checksum的部分是零,计算后填入,当对方接受数据包时,数据包再checksum一次,这时真确的包会返回0,这是校验和的精华所在

  PIP_ADAPTER_INFO padapter;//通过GetAdaptersInfo获取本机ip,本机mac,网关ip
  padapter = (IP_ADAPTER_INFO *) malloc(sizeof(IP_ADAPTER_INFO) );
  DWORD length=sizeof(IP_ADAPTER_INFO);
  if (GetAdaptersInfo( padapter, &length) == ERROR_BUFFER_OVERFLOW) {
  free(padapter);//释放内存
  padapter = (IP_ADAPTER_INFO *) malloc (length);
  }

  GetAdaptersInfo( padapter, &length);

while(padapter){

  unsigned char mygateway[255]={0};
strcpy((char *)mygateway,padapter->GatewayList.IpAddress.String);

if(mygateway[0]!=0x00) //测试GATEWAY地址,如果有就用这个INTERFACE的
{
  strncpy(myparam.myip,padapter->IpAddressList.IpAddress.String,15);
  strncpy(myparam.gatewayip,padapter->GatewayList.IpAddress.String,15);
  strcpy(classid,padapter->AdapterName);//提取classid
  strcpy(classid,classid+1);
  classid[strlen(classid)-1]=&#39;\0&#39;;

for (int i=0;i<(int)padapter->AddressLength;i++)
     myparam.mymac[i]=(int)padapter->Address[i];//拷贝6个字节的mac

break;
}

padapter=padapter->Next;//loop

}

/*
  printf("IpAddress - %s\n",myparam.myip);
  printf("Gateway IpAddress - %s\n",myparam.gatewayip);//打印获得的ip、mac
  printf("MAC Address - ");
  for(int j=0;j<6;j++)
if (j == 5)
     printf("%.2X\n\n",myparam.mymac[j]);
   else
    printf("%.2X-",myparam.mymac[j]);
*/


  ULONG MacAddr;   
  IPAddr DestIp=0;
  ULONG PhysAddrLen = 6;

  BYTE *bPhysAddr;
  int s;
  DestIp = inet_addr(myparam.gatewayip);

  memset(&MacAddr, 0xff, sizeof (MacAddr));
  SendARP(DestIp, NULL, &MacAddr, &PhysAddrLen);//通过 SendARP()获得网关的MAC,可以参考MSDN
  bPhysAddr = (BYTE *) & MacAddr;
   
   for (s = 0; s < (int) PhysAddrLen; s++)
    myparam.gatewaymac[s]=(int)bPhysAddr[s];//拷贝6个字节的mac(网关)

ETHERNETHEADER ethdr;
ethdr.eh_type=htons(IP);
for(int k=0;k<6;k++)
ethdr.eh_dst[k]=myparam.gatewaymac[k];//拷贝6个字节的mac(网关)
for(k=0;k<6;k++)
ethdr.eh_src[k]=myparam.mymac[k];//拷贝6个字节的mac(本机)

  ipheader.sourceIP=inet_addr(myparam.myip);
  ipheader.destIP=inet_addr(myparam.gatewayip);
  ipheader.checksum=checksum((unsigned short *)&ipheader,sizeof(ipheader));//校验IP首部

  PSDHEADER psdheader;
  psdheader.saddr=inet_addr(myparam.myip);
  psdheader.daddr=inet_addr(myparam.gatewayip);
  psdheader.mbz=0;
  psdheader.ptcl=IPPROTO_UDP;
  psdheader.tcpl=htons(sizeof(udpbuf));
  
  UDPHEADER udpheader;
  
//从 %systemroot%\system32\drivers\etc\services可以找到端口号
//bootps       67/udp  dhcps         #Bootstrap Protocol Server
//bootpc       68/udp  dhcpc         #Bootstrap Protocol Client

  udpheader.destport=htons(67);//htons就是把数据的两个字节互相换位
  udpheader.sourceport=htons(68);
  udpheader.udp_checksum=0;//udpheader的校验和ipheader的一样,计算校验和时checksum的部分是零,计算后填入,当对方接受数据包时,数据包再checksum一次,这时真确的包会返回0。
  udpheader.udp_length=htons(sizeof(UDPHEADER)+sizeof(mybuf));
  
  DHCPHEADER dhcpheader;
  dhcpheader.MessageType=BOOT_REQUEST;
  dhcpheader.HardwareType=ETHERNET;
  dhcpheader.HardwareAddrLen=sizeof(myparam.mymac);
  dhcpheader.Hops=0;
  dhcpheader.TranID=htonl(0x8db96125);
  dhcpheader.Secondselaps=0;
  dhcpheader.BootpFlag=htons(BROADCAST);
  dhcpheader.ClientIP=inet_addr(myparam.myip);
  dhcpheader.NextServerIP=0;
  dhcpheader.RelayAgentIP=0;
  dhcpheader.YourIP=0;

  for(int j=0;j<6;j++)
  dhcpheader.ClientMac[j]=myparam.mymac[j];//拷贝MAC

  memset(dhcpheader.PAdding,0,sizeof(dhcpheader.PAdding));//这些都为空
  memset(dhcpheader.ServerName,0,sizeof(dhcpheader.ServerName));
  memset(dhcpheader.BootFileName,0,sizeof(dhcpheader.BootFileName));
  dhcpheader.MagicCookie=0x63538263;//这是本机的
  memcpy(mybuf,&dhcpheader,sizeof(dhcpheader));

/*
DHCP_DISCOVER 0x01
DHCP_REQUEST 0x03
DHCP_DECLINE 0x04
DHCP_ACK 0x05
DHCP_NAK 0x06
DHCP_RELEASE 0x07
DHCP_INFORM 0x08
*/

  DHCPTYPE dhcptype;
  dhcptype.option.OptionNum=DHCP_MESSAGE_TYPE;
  dhcptype.option.OptionLen=sizeof(UCHAR);
  dhcptype.value=DHCP_REALEASE;
  memcpy(mybuf+sizeof(dhcpheader),&dhcptype,sizeof(dhcptype));
  
  SERVERIDEN serverid;
  serverid.option.OptionLen=sizeof(DWORD);
  serverid.option.OptionNum=SERVER_ID;
  serverid.value=inet_addr(myparam.gatewayip);//写入网关的ip
  memcpy(mybuf+sizeof(dhcpheader)+sizeof(dhcptype),&serverid,sizeof(serverid));

  CLIENTIDEN clientid;
  clientid.end=0xFF;//数据结尾
  clientid.value[0]=0x01;

  for(j=0;j<6;j++)
  clientid.value[j+1]=myparam.mymac[j]; //写入本机的mac

  clientid.option.OptionLen=sizeof(clientid.value);
  clientid.option.OptionNum=CLIENT_ID;
  memcpy(mybuf+sizeof(dhcpheader)+sizeof(dhcptype)+sizeof(serverid),&clientid,sizeof(clientid));

  memcpy(udpbuf,&udpheader,sizeof(udpheader));
  memcpy(udpbuf+sizeof(udpheader),mybuf,sizeof(mybuf));//这边+sizeof(udpheader)的意思是移动udpbuf的指针,然后把数据拷贝到udpbuf的尾端

  memcpy(udpchecksum,&psdheader,sizeof(psdheader));
  memcpy(udpchecksum+sizeof(psdheader),udpbuf,sizeof(udpbuf));
  udpheader.udp_checksum=checksum((unsigned short *)udpchecksum,sizeof(udpchecksum));//校验UDP首部和后面的数据
  memset(udpbuf,0,sizeof(udpbuf));
  memcpy(udpbuf,&udpheader,sizeof(udpheader));
  memcpy(udpbuf+sizeof(udpheader),mybuf,sizeof(mybuf));

  memcpy(ipbuf,&ethdr,sizeof(ethdr));
  memcpy(ipbuf+sizeof(ethdr),&ipheader,sizeof(ipheader));
  memcpy(ipbuf+sizeof(ipheader)+sizeof(ethdr),udpbuf,sizeof(udpbuf));

/*
for(int i=0;i<(int)sizeof(ipbuf);i++){//这里打印出构造好的数据
    static int count=1;

    if(count%16==0)
    printf("%.2X\n",ipbuf[i]);
      else
    printf("%.2X ",ipbuf[i]);

    count++;
  }
    printf("\n\n");
*/
   
ULONG len;
LPADAPTER lpadapter;
LPPACKET  lpPacket;
char adapter[65535]={0};
PacketGetAdapterNames((char*)adapter,&len);//把全部ADAPTER的名称提取到char adapter[65535]
char adapterlist[10][1024];

char * temp1;
char * temp2;
temp1=adapter;//temp1指向当前的
temp2=adapter;//temp2指向之前的
int num=0;

while((*temp1!=&#39;\0&#39;)||(*(temp1-1)!=&#39;\0&#39;)){//这边提取ADAPTER的名称,char adapter[65535]包含全部的名称,以‘\0’间隔

  if(*temp1==&#39;\0&#39;){
    memcpy(adapterlist[num],temp2,2*(temp1-temp2));
    temp2=temp1+1;
num++;
  }
temp1++;
}

int adapternum=num;
int mynum=0;
for(num=0;num<adapternum;num++){
strcpy(clsid,adapterlist[num]);//这边提取classid
strcpy(clsid,clsid+13);
clsid[strlen(clsid)-1]=&#39;\0&#39;;
if (strcmp(clsid,classid)==0)//通过classid的比较来选定ADAPTER
mynum=num;
}

lpadapter=PacketOpenAdapter(adapterlist[mynum]);//打开指定的ADAPTER
lpPacket=PacketAllocatePacket();//为包分配内存

PacketInitPacket(lpPacket,ipbuf,sizeof(ipbuf));  //把构造好的数据放入RAWPACKET

if(PacketSendPacket(lpadapter,lpPacket,TRUE)==FALSE)//发包
  {
    printf("发送失败!%d\n",GetLastError());//代码里省略了很多检查ERROR的部分,减少代码的长度
    return ;
}

PacketFreePacket(lpPacket);   //释放内存
PacketCloseAdapter(lpadapter);//关闭ADAPTER

}

TOP

一只菜鸟从你旁边飞过,我实在不知道你搞这个有什么利用价值,哪位帅哥能解释下吗,
东邪

TOP

引用:
ipconfig /?
      .....
      /release release the IP address for the specificed adapter
       .....
Example:
         ipconfig /release *con*        ... release all matching connections.
                                      eg."Local Area connection 1" or "local connection 2"
注释也忒少了,看起来真的挺累的,而且没看懂

TOP

发新话题