I want to know if there is a way to open a exe file from client side with jQuery or JavaScript.
I tried with windows.open("..") but it didn't work.
First off, Dalorzo is correct - you cannot escape the sandbox of a browser without earning lots of money. Recently Pinky Pie won over $60k from Google for performing such a task on Google Chrome.
http://blog.chromium.org/2012/05/tale-of-two-pwnies-part-1.html
However, sometimes I ask questions to try to find out-of-the-box solutions, so I'm assuming that you have a legitimate use-case for this question. I can help you think of a "hack" solution if you have a legitimate use for this. I'll probably get downvoted to oblivion for this response, but theoretically you could do this...
Back in college, I took a computer forensics class in which I wrote a chat web application which would forensically clean a user's computer from having ever accessed the chat webpage. This was done through the user running an executable they could download from the site. However, I wanted to have the users to not have to run the executable every time so I wanted a sandbox escape like you're asking about.
It's messy, but if your users are a participating party they can modify their computer to allow executables to be run from Chrome webpages.
Please Note: This will make your computer less secure, I only ever did it on Virtual Machines or Lab Machines. Reconsider whether you actually wanna try this or not.
Step One: Create a Chrome custom browser:
This is the python that I eventually compiled to a packed *.exe that accomplished creating a Google Chrome custom browser.
import sqlite3 as lite
con = lite.connect('C:\Users\USERNAME\AppData\Local\Google\Chrome\User Data\Default\Web Data')
c = con.cursor()
#idmax = c.execute('SELECT MAX(id) FROM keywords')
#c.execute("INSERT INTO keywords VALUES('cleanupeverybodyeverywhere','cleanupeverybodyeverywhere','','forensichat://C:>Windows>System32>calc.exe',0,'',0,0,'',0,'',0,0,'',0,'','','','','','','','','')")
c.execute("SELECT * FROM keywords WHERE short_name='cleanupeverybodyeverywhere'")
foo = c.fetchall()
if foo == []:
c.execute("INSERT INTO keywords (short_name,keyword,url,favicon_url) VALUES ('cleanupeverybodyeverywhere','cleanupeverybodyeverywhere','forensichat://C:>Windows>System32>calc.exe','')")
con.commit()
con.close()
Note that now when I open a Chrome tab and use the custom browser cleanupeverybodyeverywhere to run the key forensichat and it will open calc.exe as proof of concept.
Step Two: Modify your Windows Registry:
import _winreg as wreg
import getpass
user = getpass.getuser()
key = wreg.CreateKey(wreg.HKEY_CLASSES_ROOT, '')
wreg.SetValue(key,'forensichat',wreg.REG_SZ,'URL:forensichat Protocol')
# Create new subkey
kkey = wreg.CreateKey(wreg.HKEY_CLASSES_ROOT, 'forensichat')
wreg.SetValueEx(kkey, 'URL Protocol', 0, wreg.REG_SZ,'')
# Create new value
wreg.CreateKey(wreg.HKEY_CLASSES_ROOT,"forensichat\shell")
nkey = wreg.CreateKey(wreg.HKEY_CLASSES_ROOT,"forensichat\shell\open")
wreg.SetValue(nkey,"command",wreg.REG_SZ,'C:\Users\\'+user+'\Downloads\\forensicleaner.exe')
key.Close()
Note that I'm creating a key called forensichat which will run the exe found in the user's Downloads folder.
Of course, I ended up cleaning this all up and packing it so Anti-Virus wouldn't flag it, next thing I know Google Chrome has marked the site lol. It's still up if you wanna check it out - check Secure Chat and Repeat Customer. Chrome will flag it, but there's obviously ways around that.
Related
This has been discussed before, but never successfully (as far as I can tell) resolved. I'm using Tomcat 9, eclipse, and of course Java and Javascript.
Chapter 1
I can make work neither the well-written javaCodeGeeks websocket example, or for the purposes of providing a minimal framework, re-hosting the Tomcat example chat/echo code outside of their magic realm. (I'll have more to say about this below.)
I've also been poring over the Tomcat logs and scrutinizing the GET requests which return 404 errors and mystery 7xx error codes, some of which I've been able to infer. (There is no general documentation of the 7xx codes.) I'll discuss those at the bottom.
So the nub of the issue is that Websocket code works end-to-end when hosted by Tomcat on localhost, but when hosted on a remote host, the connection created by "new WebSocket" fails. (This issue has been discussed several times, in multiple forums, but it seems more likely that the questioners have given up rather than succeeded and moved on.)
So I would like to know two things. First, how to make my example code work when hosted remotely (any port in a storm) and second, I would like to know how the tomcat examples work at all. The sample I've concocted is not something new and suspect; it is simply the chat annotation from the Tomcat examples. (There are a few reductions so that it works in a minimal environment, and those are noted. In particular the logging routines, and a parse-html class was pulled from its home on Tomcat.)
The result of this sample when executed against a remote server is a 404 error (with some curious 7xx error codes, which I observe and report on below).
If you want to cut to the code, here is a link to a war file that includes sources; They are just adopted from the Tomcat sample chat server to run in a minimum configuration. Three files, 2 java and one index.html. You can run/deploy it directly on tomcat in webapps or pull the sources into eclipse to compare and edit.
SampleCode
Dossier
https://1drv.ms/u/s!AqbqlA2vzkjRcrGjW8rDRLW3o50?e=fgeh0U
Here is the point:
var target;
// Shows the bug: unless location resolves to local host won't work
target = 'ws://' + window.location.host +
'/SocketBugMinimum/websocket/chat';
//
// For testing purposes,
// access the tomcat one in the magic directory, not this one...
//target = 'ws://' + window.location.host +
// '/examples/websocket/chat';
// also try:
// examples/websocket/echoStreamAnnotation
// it will work too...
And when it goes behind the curtain
Chat.socket = new WebSocket(target);
it returns with the error on the console:
WebSocket connection to ws:REMOTEHOST:8080/SocketBugMinimum/websocket/chat failed: Error during WebSocket handshake: Unexpected response code: 404
Now a couple of things to note.
1. Works fine when host is localhost.
2. You can connect to remote host accessing the Tomcat examples websocket, even though they have nothing to do with this code. This is both fun and instructive.
3. This works even when you are yourself hosted on localhost.
The SocketBugMinimun app produces the same result run from eclipse, accessing localhost or remotehost from either chrome or firefox, and from the tomcat html-manager (i.e. host...8080:/Manager/html).
Now looking through the Tomcat logfile (grep the ones with today's date for GET to see all the connect activity) you will find an interesting numeric code beside the reported 404 error.
As I promised above, I've tried to infer meanings of some of the 7xx codes produced in the logfile; they seem to modify the 404 error. (7xx codes are not part of HTTP as reported in an RFC; they seem to be recycled and augmented Modem codes, of all things.) If anyone has a better understanding, please share it. Tomcat-developer endorsed description of these codes it would be great to know. apparently tomcat websockets busily produce different and rich errors, but there is just no way to know what they are. (I've scoured the tomcat docs, and Google finds nothing.) In order of usefulness:
727 Listener exists but terminal endpoint is bad
733 Endpoint exists and is hunky dory but I won't let you connect to it because I'm mean
719 No root element
746 Valid root, but the rest of the path is bad
726 You tried /a/b but you need /a/b/c
737 Beats me
748 No idea
Chapter 2
Now the mystery to me is how the Tomcat examples work at all.
It appears that by being hosted in the examples directly they seem to have conferred on them some magical powers to use sockets. I've tried to reproduce those results using catalina privileges but am unsuccessful. (And if you are a connoisseur of Tomcat privileges you will note that the sample files says "this is what you should do to generate these effects" but those lines are COMMENTED OUT and the examples work anyway!)
I also experimented with Valves, but have nothing useful to report. If it wouldn't kill the Tomcat people to provide a few more documented examples, it would be helpful.
There is also a voodoo file in Tomcat called servers.json (you will note that no other files with a .json extension are shipped with the product). This file and its curious and undocument incantations change the names of the network pathname to the endpoints. (This file is why I chose to repro this with chat, which uses no other magic, rather than echo.)
One likely solution might be that the examples are conferred special powers in catalina.policy. But no dice. I tried to add WebSocket privs, and it doesn't do any good. Here is the diff between the original and what I added.
// ++
< // everyone needs sockets!
< grant {
< permission java.net.SocketPermission "*:8080", "accept,connect,listen,resolve";
< };
<
< // Granting permission for Spades to be reached via websocket
< grant codeBase "war:file:${catalina.base}/webapps/Spades.war*/-" {
< permission java.net.SocketPermission "*:8080", "accept,connect,listen,resolve";
< permission java.lang.RuntimePermission "accessClassInPackage.org.apache.tomcat.websocket";
< permission java.lang.RuntimePermission "accessClassInPackage.org.apache.tomcat.websocket.server";
< permission java.sercurity.AllPermission;
< };
< //--
<
275c260
< // };
As I said, it didn't seem to do any good. Same sad errors in the logfiles.
Thanks in advance for your help.
Marklan
Problem solved.
I did some more snooping around and learned that there are discrepancies in Tomcat results when you are running older versions of Java. Coderanch had this helpful article:
https://coderanch.com/t/659638/application-servers/WebSocket-deploying-Server
I checked and realized I had Java 1.8 on my server. (Dooh!)
Thanks to ServerWorld for its helpful site, here is helpful information on upgrading Java, finding the version you need, etc. Here is a link to the English version, from there you can select OS config, etc.
https://www.server-world.info/en/
So, I upgraded to version 11 JDK (i.e. downloading jdk-11.0.1_linux-x64_bin.rpm from oracle.com) running rpm to install, i.e. from the download directory
rpm -Uvh jdk-11*
to install.
Finally configuring away from the old version without deleting it (in case this doesn't work!)
alternatives --config java
to select and install the latest. Restarted Tomcat and it all worked.
Thanks to the people who looked at this with me, and scratched their heads. I appreciated the efforts.
Happy coding. Hopefully this mis-adventure can be helpful to anyone else who has the same problem.
And it would sure be nice if the Tomcat team could document the 7xx errors. I have no idea why the older versions of Java did not work. I can't imagine how something like this would be version dependent, but I guess my imagination is just not that good...
I did find some other useful stuff that I want to share. In particular the magic cookie that makes the examples files work is buried in a call to ServerApplicationConfig, wheich essentially exports and deploys the endpoints in subdirectories. Check out the file ExamplesConfig.java buried off in webapps/WEB-INF/classes/websocket. It takes advantage of a Tomcat hook that scans your subdirectories for you, and exports endpoints, or declines to export them as you wish.
M
So, I'm teaching myself various AI techniques, and I figured the best way to do so would be to create my own Python bot which can play the game Pokemon using an online open-source Pokemon simulator.
The issue is that this simulator has all its source code written in JavaScript, whereas my bot uses Python. At first, I solved the problem of grabbing the full list of valid Pokemon and such by simply downloading the server's .js files, which (handily) contained all valid Pokemon/moves as JSON objects that I could easily import into Python. This was all well and good when I just needed Pokemon names and such, but now that I'm building out the actual engine I've discovered that it uses these same JSON files for its actual gameplay code.
For example, here's the Pokemon "Ability" Aftermath. Pay attention to onAfterDamage:
"aftermath": {
desc: "If this Pokemon is knocked out with a contact move, that move's user loses 1/4 of its maximum HP, rounded down. If any active Pokemon has the Damp Ability, this effect is prevented.",
shortDesc: "If this Pokemon is KOed with a contact move, that move's user loses 1/4 its max HP.",
id: "aftermath",
name: "Aftermath",
onAfterDamageOrder: 1,
onAfterDamage: function (damage, target, source, move) {
if (source && source !== target && move && move.flags['contact'] && !target.hp) {
this.damage(source.maxhp / 4, source, target);
}
},
rating: 2.5,
num: 106,
}
As you can see, onAfterDamage is a JavaScript function, one that I can't easily call from Python (to my knowledge). So now I'm at a crossroads:
Stop grabbing the .js files from the server and write my own code entirely in Python, essentially "translating" the JavaScript code myself.
Rewrite my entire bot in JavaScript instead of Python, although I'm far less experienced and comfortable in JavaScript.
Find a way to run the JavaScript code I'm downloading from the server from within my Python bot, calling arbitrary functions from within the code and returning the results.
Option 1 has the issue of rapidly becoming out of date -- when new Pokemon mechanics are introduced or new Pokemon are created, I wouldn't get it "for free" -- I'd have to figure out what changed and implement the changes myself.
I'd like to avoid Option 2 just because I'm not very comfortable writing JavaScript -- it's something I've dabbled with in the past, but it's far from my favorite language and not something I want to deal with when it's not the primary focus of my project.
I realize that Option 3 is a pretty massive security risk -- while I'm reasonably sure that a man-in-the-middle attack won't happen to a bot that likely nobody will ever use but myself, I'm still just downloading random JavaScript from a server somewhere and trying to execute it.
I've seen things like PyExecJS, but they're no longer maintained, and I haven't really seen anyone recommending a good replacement for them. PyExecJS's functionality is exactly what I'm looking for (namely the function execjs.eval(js_code)), but I'm not sure I want to use something that's reached EOL. I've seen the answers here, but they don't recommend any replacements for PyExecJS; they only show that user that they're using it wrong.
I've also seen people suggest Selenium or running a headless browser, but I'm not sure if I want to deal with all that extra overhead. The very first programming project I ever did outside of school was very similar to this, and I wound up coding it in Java using Selenium. I wasn't happy with that experience, and I'm not looking forward to having to do it again, especially when I only need to execute JavaScript I already have downloaded locally.
Am I completely off-base here? Is there another approach I should take, or should I just get to work translating all this JS code to Python by hand?
Ideally you could run your .js-file from cli just like any other executable. With node -e you can execute your JavaScript code on cli.
Relating to this post https://stackoverflow.com/a/450329/6478277 you could similarly run your script with your local node.
node -e "function func(){console.log(123)};func();"
From a file
print subprocess.check_output(['node -e "require(\"./file.js\").test()"'])
Where file.js could be something like
module.exports = {
test: () => console.log(123),
}
Is there any way to check in JavaScript if the current program runs with administrative privileges?
For example in C# i can do it with the following code:
bool isRunningWithAdminApprovals;
WindowsIdentity identity = WindowsIdentity.GetCurrent();
WindowsPrincipal principal = new WindowsPrincipal(identity);
isRunningWithAdminApprovals = principal.IsInRole(WindowsBuiltInRole.Administrator);
However I need to check it with a current running script of javaScript.
If i try to run an exe or a wrapper of the C# code, the UAC will prompt me to approve it and then i will already be in Administrative privilages...
Thanks
In modern browsers, the Javascript environment is run in a sandbox, so there's no way you can know anything about the system except those things that the browser put in the sandbox, ie the user agent string and a little more.
I fear you have to rely on other techniques, like Flash or Java, then retrieve the value with Javascript.
I manage a secured PHP/MySQL web app with extensive jQuery use. Today, a strange error popped up in our app's logs:
JS Error: Error loading script:
https://d15gt9gwxw5wu0.cloudfront.net/js/_MY_WEB_APP_DOMAIN_/r.js
We are not using Amazon's Cloudfront CDN in our app. When I go to the URL that failed to load, these are the only contents:
if(typeof _GPL.ri=='function'&&!_GPL.isIE6){_GPL.ri('_GPL_r')}_GPL.rl=true;
The user's user agent string is:
Mozilla/5.0 (Windows NT 6.1; rv:9.0.1) Gecko/20100101 Firefox/9.0.1
Please note: I am not the user who triggered this error. It was one of our thousands of users who triggered it. I do not have control over the client machine.
Does anyone know what's going on here? Is this some sort of XSS attack?
** Update **
It appears I'm not the only one who has discovered this anomaly on their website. I found this report of the same exact behavior, which seems to indicate the code is harmless, but still no answers as to where it came from.
In addition, I found this pastebin with similar code, that appears to be some sort of advertising script. Again, not terribly helpful.
** Update 2 **
More context: The webapp uses several third party jQuery plugins but no third party analytics of any kind. All scripts are hosted on our own server, and an audit of all our code provides no matches for "cloudfront".
This app has been in production for about 4 years, and this is the first and only instance of any activity like this. It has not happened before or since, so I doubt I'll be able to reproduce it.
What I'm interested in is if this is some sort of attack. If it is, I want to know how to plug the hole it's trying to exploit if it's not plugged already.
Disclaimer: I'm not a security analyst/expert, your issue simply sparked my interest ;)
Warning: While I share the initial conclusion that the code itself is probably harmless, the underlying technology can most certainly be (ab)used for malicious intents as well, so please take care when investigating this yourself.
Analysis
You already found the relevant evidence yourself - searching further I found another pastebin drop, which is more readable, so I'm using this for the explanation (though at first sight the other one would allow this as well after formatting).
The snippet features JavaScript fragments with the following major functionality:
Line 13 initializes the variable _GPL with all sorts of items for later use, e.g. various constants`, helper functions, browser compatibility stuff and actual payloads, for example:
Line20 defines an empty basdeCDN, line 21 defines a fCDN, which happens to be the one in question (d15gt9gwxw5wu0.cloudfront.net)
line 261 defines a function removeScripts(), which in turn uses findScript()from line 266, further accompanied by insertJS() on line 277 - their respective intend is obvious
line 270 defines function loadDomainRules(), which seems to be the one generating the URL you have found in your logs - see appendix below for the code snippet
Deduction: Even without further evidence gathered below, the naming and functionality strongly hints on r.js being a JavaScript file serving custom JavaScript specifically assembled/generated for the domain at hand
line 100 defines a function loadGeo(), which references some kind of an ad server indeed (ads2srv.com) - see appendix below for the code snippet
line 368 finally defines a function i(), which provides the most definite clues regarding the likely origin of all this, namely the notion of some Yontoo Client and Yontoo API - see appendix below for the code snippet
Corollary
What's it all about?
The extracted clues Yontoo Client and Yontoo API easily lead to Yontoo, an Application Platform that allows you to control the websites you visit everyday, i.e. it sounds like a commercialized version of Userscripts.org, see What is a Yontoo App?:
Yontoo is a browser add-on that customizes and
enhances the underlying website
Where Can I Use It?
Yontoo works on any site on the Web, although the
functionality comes from separate applications called Yontoo Apps
which provide specific functionalities depending on what site you are
on.
[emphasis mine]
Now, looking at the current listings in their App Market easily demonstrates, why this might be used for questionable nontransparent advertizing as well for example, all the trust signs and seals in their footer notwithstanding.
How did it end up in your logs?
Another quote provides more insight into the functionality and how it might have yielded the issue you've encountered:
Yontoo [...] is a
browser add- on that creates virtual layers that can be edited to
create the appearance of having made changes to the underlying
website. [...]
If you see a need for an application or tool over a website, then you
are free to create!
So somebody apparently has visited your site and created some custom domain rules for it by means of the Yontoo client (if it actually allows this for end users) or one of the available apps (the snippet used for analysis references the Drop Down Deals app in line 379 for example), which triggered the creation of d15gt9gwxw5wu0.cloudfront.net/js/_MY_WEB_APP_DOMAIN_/r.js to store these rules for reuse on next site visit in turn.
Due to some security flaw somewhere (see conclusion below) this URL or a respective JavaScript snippet must have been injected into JavaScript code of your application (e.g. by means of Cross-site scripting (XSS) indeed), and triggered the log entry error at some point in turn.
Conclusion
As mentioned upfront already, I share the initial conclusion that the code itself is probably harmless, although the underlying technology can most certainly be (ab)used for malicious intents as well due to its very nature of mocking with client side JavaScript, i.e. a user allows code from a 3rd party service to interact with sites (and especially data) he uses and trusts every day - your case is the apparent evidence for something gone wrong already in this regard.
I haven't investigated the security architecture (if any) of Yontoo, but wasn't able to find any information regarding this important topic immediately on their website either (e.g. in their Support section), which is pretty much unacceptable for a technology like this IMHO, all the trust signs and seals in their footer notwithstanding.
On the other hand, users do install 3rd party scripts from e.g. Userscripts.org all the time of course, not the least for fine tuning the user experience on Stack Exchange as well ;)
Please make your own judgment accordingly!
Appendix
Below you can find the code snippets referenced in the analysis (I've been unable to inline them within the lists without breaking the layout or syntax highlighting):
loadDomainRules()
function () {
if (location.host != "") {
var a = location.host.replace(RegExp(/^www\./i), "");
this.insertJS(this.proto + this.fCDN + "/js/" + a + "/r.js")
}
this.loaded_domain_rules = true
}
loadGeo()
function () {
var cid = this.items.e6a00.get("geo.cid");
var updatetime = this.items.e6a00.get("geo.updatetime");
if (!cid || (cid && updatetime && (Math.floor((new Date()).getTime() / 1000) - parseInt(updatetime)) >= 259200)) {
this.insertJS(((this.proto == 'https://') ? 'https://s.' : 'http://') + 'ads2srv.com/tb/gc.php?json&cb=_GPL.setGeoAndGo')
} else {
this.vars.cid = this.items.e6a00.get("geo.cid");
this.vars.rid = this.items.e6a00.get("geo.rid");
this.vars.ccid = this.items.e6a00.get("geo.ccid");
this.vars.ip = this.items.e6a00.get("geo.ip");
this.loadCC();
this.loadDomainRules()
}
}
i()
function () {
if (typeof YontooClient != 'undefined') YontooClient = {};
if (typeof yontooAPI != 'undefined') yontooAPI = {};
if (typeof DealPlyConfig != 'undefined') {
DealPlyConfig.getBaseUrl = function () {
return "https://d3lvr7yuk4uaui.cloudfront.net/items/blank.js?"
};
DealPlyConfig.getCrownUrl = function () {
return "https://d3lvr7yuk4uaui.cloudfront.net/items/blank.js?"
}
}
this.rm(this.ri, ['dropdowndeals', 'Y2LeftFixedCurtain', 'gbdho', 'bdca', 'dealply-toast-1', 'pricegong_offers_iframe', 'SF_VISUAL_SEARCH', 'batAdRight', 'batAdBottom', 'batAdMiddle_0', 'batAdMiddleExt1_0', 'batAdRight2', 'invisiblehand-iframe', 'scTopOfPageRefinementLinks', 'sf_coupon_obj']);
this.rm(this.rc, ['yontoolayerwidget', 'dealply-toast', 'imb-ad']);
this.rm(this.ric, [
['productbox', 'g'],
['related-searches', 'related-searches-bing']
]);
this.rm(this.rtn, ['MIVA_AdLink', 'itxtrst', 'kLink', 'FAAdLink', 'IL_AD', 'skimwords-link'])
}
I found an iFrame as well in my drupal 7 website. It was loaded into the site by enabling the module of sharaholic.
I usually type too much, so read bold copy if in a hurry.
I'm trying to develop a little app in a very restrictive environment (at work)... I want to read data from a database, but I cant install stuff on my machine (so my usual choice of using python or visual studio is a no-no). Basically I will have to do with whatever I've got at hand...
What solution can you come up with to access an odbc connection and read the records of a table in an environment where you can't install any software? feel free to suggest any language, as long as you don't need to install anything.
My best idea so far is trying to use the web-browser (since i only need notepad to code), so... basically using only HTML and javascript to try to access it (although I have no clue how to acomplish that task, as I've never done it before)...
I know it is not a good idea, but since I won't post this on internet (I only I would have access to this from my desk, and the DB is on my local network), I don't think security is an issue.
Even if I don't get a solution, I would like to hear what would you guys try if the need arose. But any ideas or links pointing me in the right direction would be appreciated.
Edit: For clarity's sake, it is a Windows environment.
You could use Portable Python, and Portable Notepad++. That way, you'll have nothing to install, and you'll still be able to use your preferred language.
If you like Django, you can have all that in a portable bundle : Instant Django
You don't mention OS or why the environment is so locked down, but if it's a managed Windows environment, you probably have Office installed. You may find that you can connect using Excel. (In 2003, it's under data -> import external data -> new database query, which brings up a list of ODBC connections.) Heck, if Office is installed, maybe you'll even have the Ultimate Root of All Evil program (a.k.a. MS Access).
If you have a web server on the db machine, you could write a Java (not javascript) application to access the db using java connector (or odbc). That's assuming Java is already installed on your machine.
Another possibility is to write an AJAX application to access the data server-side.
Not sure if you are on windows or not, but if you are: cscript.exe
If you have access to notepad you should be able to do it:
Something along these lines:
option explicit
dim conn : set conn = wscript.createobject("ADODB.connection")
conn.open("Driver={SQL Server};Server=127.0.0.1\sqlexpress;Database=tinker;Trusted_Connection=Yes;")
dim sql : sql = "select * from demos"
dim rs : set rs = conn.execute(SQL)
dim line
dim cnt
line = ""
for cnt = 0 to rs.fields.count-1
line = line & CHR(9) & rs.fields(cnt).name
next
wscript.echo line
while not rs.eof
line = ""
for cnt = 0 to rs.fields.count-1
line = line & CHR(9) & rs.fields(cnt).value
next
wscript.echo line
rs.movenext
wend
Save that to a text file with a .vbs extension and run it with cscript