下了一堆jpg图片却被FireFox保存为html文件。Windows资源管理器自带的批量重命名功能对修改文件后缀名无能为力,TC又不会用,所以只能写脚本。不会的命令查一下http://www.ss64.com/

@echo off&setlocal EnableDelayedExpansion
set i=1
for /f %%G in (’dir /b *.html’) do (
ren “%%G” “!i!.jpg”
set/a i+=1
)

保存为ren.bat文件,运行后把当前目录的html文件重命名为jpg。

一个Linux脚本

#!/bin/bash
for file in *.so.*; do
ln -s $file `echo $file | awk -F. ‘{ print $1″.”$2 }’`
done

gvim as IDE

八月 16th, 2008

Linux下大部分项目代码是用makefile组织的,一些用MingW或Cygwin等工具移植到Windows的项目也保持了这种一致,只有一个configure后自动生成的MakeFile文件来组织整个项目的结构,这种方式虽然简洁高效并且通用性好,但显然没有VS提供的sln管理方式来的方便。不管怎么样,既然不能用vs干脆就用vim了。
早听说vim+Cscope很强大,正好试一下。
首先理清一下概念。Cscope是一个独立的代码分析工具,除了vim也可以被emace和其他软件调用。Vim的-enable-cscope编译选项,只是内置提供了调用cscope的接口,cscope程序还是要单独下载的。
阅读源码需要的最基本功能有快速跳转到函数定义的位置,查看函数调用了哪些函数,并被哪些函数调用等,cscope通过预分析代码,建立一个存储这些关系的数据库来实现需要的功能。

下载http://cscope.sourceforge.net/cscope_maps.vim放到vim到plugin目录,这个文件定义了一些快捷键,根据需要自己修改。

下载Cscope的win32版http://iamphet.nm.ru/cscope/index.html,放到gvim.exe所在的文件夹,方便起见把gvim的目录加到系统Path路径里,然后开一个cmd切换到要阅读的源码目录,运行cscope -Rbq它会在源码目录下生成cscope.out等几个文件。然后用vim打开代码文件,就可以用cscope了。

    在Vim命令模式下用cs add d:\src\cscope.out连接之前生成的数据库,vim会自动加载当前目录下的cscope.out文件(cscope_maps.vim里定义的),而且之后搜索定位文件都是通过相对路径,所以直接在源码顶层目录打开一个文件开始浏览代码会方便一点。

    生成数据库时用的参数

    • -R: 在生成索引文件时,搜索子目录树中的代码
    • -b: 只生成索引文件,不进入cscope的界面
    • -q: 生成cscope.in.out和cscope.po.out文件,加快cscope的索引速度
    • -k: 在生成索引文件时,不搜索/usr/include目录
    • -i: 如果保存文件列表的文件名不是cscope.files时,需要加此选项告诉cscope到哪儿去找源文件列表。可以使用“-”,表示由标准输入获得文件列表。
    • -I dir: 在-I选项指出的目录中查找头文件
    • -u: 扫描所有文件,重新生成交叉索引文件
    • -C: 在搜索时忽略大小写
    • -P path: 在以相对路径表示的文件前加上的path,这样,你不用切换到你数据库文件所在的目录也可以使用它了。

    浏览代码时用的参数

    • s: 查找C语言符号,即查找函数名、宏、枚举值等出现的地方
    • g: 查找函数、宏、枚举等定义的位置,类似ctags所提供的功能
    • d: 查找本函数调用的函数
    • c: 查找调用本函数的函数
    • t: 查找指定的字符串
    • e: 查找egrep模式,相当于egrep功能,但查找速度快多了
    • f: 查找并打开文件,类似vim的find功能
    • i: 查找包含本文件的文件

    浏览代码时先用cs show看一下有没有连上cscope数据库。
    想查找foo2函数在那里定义,可以在命令模式下,输入:cs f s foo2,也可以在Normal模式下,把光标停在函数名上,输入Ctrl+\,再按s键,这也是在cscope_maps.vim里定义的,果然要方便一点,但要是能弄成一种CScope模式就好了,每次都要先输入Ctrl+\也很麻烦。
    官网http://cscope.sourceforge.net/
    另一种组合是Ctags+taglist。
    ctags在功能上比cscope要弱一点,但taglist只支持ctags生成的数据库,taglist是Vim上下载量最大的插件,它提供一个额外的窗口显示文件,变量,函数等信息,这样Vim看起来就更像一个IDE了。
    ctags http://ctags.sourceforge.net/
    taglist http://www.vim.org/scripts/script.php?script_id=273
    按照说明把下载的文件放到相应目录后重启gVim,没有出现问题的话这时在命令模式下输入Tlist就可以激活taglist的窗口,然后用TlistAddFile或TlistAddFilesRecursivei打开其他文件,浏览时ctrl+]查看函数的定义, ctrl+o返回原来位置。

    下面是我的gvim截图

    用Cscope的Ctrl+\后c查找uninit_player在哪里被调用

    在sf找到两个致力于低权限帐号增强安全性开源的项目,
    http://sourceforge.net/projects/sudowin
    http://sudown.sourceforge.net/
    虽然在我的windows 2003 SD上装了都不能使用。
    简单的看了一下代码,sudown是VC2005写的,一共三个项目,主要的工作的sudown做的,其他两个都是在调用sudown提供的功能。它的原理是,在普通用户登录系统以后,再把它加入到管理员组中,这个时候explorer等程序已经在运行了,而系统进程winlogon在创建他们的时候,用户还没有管理员权限,所以他们都是在以低权限运行,而你在explorer中双击运行的程序,也会继承这个低权限的,虽然你的帐号有管理员权限。然后当你logoff到时候,在把你的帐号从管理员组中移除。也就是说,你只在登录以后是管理员,其他时候都是一个普通帐号,比较tricky。具体是用到了Winlogon Notify来截获系统登录退出的消息。

    sudowin是用C#写的,需要.net 2.0,用vs打开一看居然有14个项目,一个个看显然不太现实,想了一下C#做这种API密集型事情肯定会大量用到DllImport,就把它当关键字搜索整个Solution,很快定位到一个叫Server项目下的Win32.cs文件。这里对大量的API进行了包装,其中比较引人注目的是LogonUser和CreateProcessAsUse这两个函数。MSDN一下就可以发现这两个函数正是实现runas需要的。LogonUser用指定的帐号密码登录,获取一个代表用户的token,再用这个token调用CreateProcessAsUse创建对应权限的进程。
    事实上反汇编一下ruanas.exe可以发现,在它的Imports表里面可以看到一个叫CreateProcessAsUserW的函数,MSDN对其的说明是:
    The CreateProcessWithLogonW and CreateProcessWithTokenW functions are similar to the CreateProcessAsUser function, except that the caller does not need to call the LogonUser function to authenticate the user and get a token.
    http://msdn.microsoft.com/en-us/library/ms682431(VS.85).aspx
    猜测sudowin就是runas的另一个实现,因为没有用过也不知道它做了哪些改善。

    因为这两个程序都没有在我的系统上正常工作,所以还是觉得我之前的那个想法更好一点。只是很沮丧的发现runas有一个/env选项,可以保留当前用户环境进行操作,让我关于重用用户profile的探索显得很多余。

    附上一个关于Least-privileged User Account 的网站。
    http://nonadmin.editme.com/

    windows XP/2003下的UAC

    七月 31st, 2008

    要增强计算机抵抗病毒木马的能力,最有效的方法是使用低权限帐号执行日常操作,特别是在现在恶意软件普遍采用驱动方式直入系统内核进行操作的环境下,这要比装好几个杀毒软件更能保护你的电脑。Windows Vista在安全上的最大改进就是引入了UAC机制,确保高权限不被滥用。而在Vista之前的系统,微软也提供了runas工具,但操作不太方便,本来系统的用户友好度和安全性就是对立的两个方面,但显然runas在这两者之间的平衡性需要调整一下。

    下面这个方法可以不用一次次的用runas运行程序,而是一次性的获得一个管理员权限环境,执行完要求高权限的操作后再返回普通权限环境。

    首先创建两个账户,一个Adimistrator一个user。

    平时使用一个User权限的帐号,上网看影片什么的,等到需要管理员权限的时候,用runas开一个Adimistrator帐号的CMD,在里面运行taskmgr或tskill杀死explorer,然后重开一个explorer,这时的explorer就有管理权限了,用鼠标双击运行的程序也会继承这个权限,方便执行高权限操作。最后用同样的方法回到user用户环境。

    貌似更复杂了,但这个过程可以写成脚本或程序,之后的操作就简单了。

    但是有一点,runas以后用户配置文件会改变,这样桌面和程序设置之类的信息就无法保持连贯,能不能让两个帐号用同一个Profile呢?

    Windows所有的配置信息都放在注册表。

    而注册表本身是几个文件,分别放在系统目录\windows\system32\config和用户主目录下面。详细信息记录在注册表的HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\hivelist这里。

    注册表中跟用户环境有关的信息在以下

    HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders

    HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders

    其值都是一些跟用户主目录相关的内容,其中有一个%USERPROFILE%变量,如果能改变它的值就可以一劳永逸的改变profile位置了,开一个cmd运行一下set,可以看到当前USERPROFILE的值,通常是C:\Documents and Settings\user这样的,而它的值是在

    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList

    这里设置的,profilelist下有很多项,都是以帐号的SID名命的,帐号sid可以通过systeminternal工具里的 psgetsid获得,如psgetsid Administrator可以得到Administrator这个帐号的sid,一般是S开头加一串数字并以500结尾,具体命名规则《Windows Internals》这本书上有介绍。找到对应的项下面的ProfileImagePath键值,这就是%USERPROFILE%变量对应的值,修改它的值使之指向其他用户的profile目录,注销重登陆,再运行set命令,就可以发现,USERPROFILE到值已经被改变了。

    不过实际操作过程中有很多限制,

    首先必须用Administrator帐号复用user帐号的profile,反之会因为user到权限不够访问不了admin的profile而无法正常登录(windows会自动创建一个TEMP的profile以供临时使用),试了一下在文件ACL中给user增加完全控制权限也不行。

    而先用administrator登录后,不重启只是注销再登录user系统会提示“Windows 不能加载本地存储的配置文件……安全权限不足……”这样的提示,然后为你创建一个TEMP的profile。

    另开一个管理员帐号用handle考察一下发现administrator注销以后System这个进程依然打开着administrator 的profile目录中的NTUSER.DAT也就是HKEY_CURRENT_USER注册表的文件,因为user也要用这个文件,但又抢不过 admin所以就登录失败了。

    设备管理器里面双击你的网卡,打开高级标签,属性里面有一个Network Address,默认的值是”不存在”,上面的方框可以手动输入任意新的物理地址,当然具体情况,根据装的网卡驱动不同而有所差别。网卡物理地址是48位的,表示成16进制就是12个数字,形如0800200070DF,其中前六位是厂商,如080020开头说明是SUN公司生产的。具体列表见http://www.erg.abdn.ac.uk/users/gorry/course/lan-pages/mac-vendor-codes.html

    我在修改的时候, 开了一个Regmon监视写注册表操作,发现HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002bE10318}007\NetworkAddress的键值被改变成刚设置的MAC地址值,于是试了一下直接在注册表里修改,然后重启一下网络连接,发现果然也可以这样修改MAC地址。就写了一个脚本自动修改。

    Dim objShell
    Set objShell = CreateObject(”Wscript.Shell”)
    objShell.RegWrite “HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002bE10318}007\NetworkAddress”,”0800200070DF”
    Return =objShell.Run(”netsh int set interface name=”"本地连接”" admin=disabled”,1,true)
    Return =objShell.Run(”netsh int set interface name=”"本地连接”" admin=enabled”,1,true)

    重启网络连接的方法是从这里学来的http://www.eecx.com/ping/article.asp?id=149,另外发现WSH语法里面引号里转义引号是用两个引号,这个让我小纠结了一会。

    Windows跨网段共享文件

    七月 14th, 2008

    网上邻居的文件共享协议是基于TCP/IP的,既然如此文件共享应该在互联网范围内可用,但事实上,在一般情况下两个不同子网中的电脑都不能共享文件。这主要是因为子网间通信需要经过路由,而大部分路由器都屏蔽了Windows文件共享协议用到的445,139这些端口。
    所以只要能更改共享文件用到的端口,就可以突破这个限制了。
    Windows用的文件共享协议是SMB,Linux下也有一个实现Samba。
    Windows 2000以后的SMB可以直接通过TCP/IP运行,用的是445端口。
    但是为了兼容2000以前的Windows,SMB也通过NetBIOS over TCP/IP运行,使用139端口。如果网络中没有2000以前的机器,可以禁用之,完全是冗余的东西而且有不小的安全隐患,在TCP/IP协议属性里更改,不用重启立即生效。当然也可以不禁用,因为等我们改了445端口以后,正常的Windows机器就无法通过455端口和我们共享文件了,这时候139端口就有用了。

    修改SMB端口号,只需在注册表中添加下面两个键值,22b即555是新端口号可以改为其他的,但两台电脑要能互相访问共享必须改成同样的端口号。
    [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\NetBT\Parameters\Smb]
    "SessionPort"=dword:0000022b
    "DatagramPort"=dword:0000022b

    重启后,开一个CMD运行netstat -an | findstr 455,检查455端口是否被关闭。
    建议把两个键值导出为reg文件,去所有想要共享文件的电脑上双击运行一下。
    另外如果有这个键值"UseNewSmb"=dword:00000001先删除之。

    更详细的信息见
    http://www.xfocus.net/releases/200408/a723.html
    http://www.petri.co.il/what%27s_port_445_in_w2k_xp_2003.htm

    因为学校网络的特殊性,经常要登录学校网关和切换浏览器代理不胜其烦,Google了一下也没有更好的办法就自己写了两个VBS的脚本。

    rem 开启IE代理
    Set WshShell = WScript.CreateObject(”WScript.Shell”)
    WshShell.RegWrite “HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ProxyEnable”, 1 ,”REG_DWORD”

    rem 关闭IE代理
    Set WshShell = WScript.CreateObject(”WScript.Shell”)
    WshShell.RegWrite “HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ProxyEnable”, 0 ,”REG_DWORD”

    Regmon一下就可以发现,设置IE代理的时候就是在改ProxyEnable这个键值,只是手动设置的时候IE可以立即更新代理设置,这种方法只能在新开一个IE后才能有效。FireFox的话可以装一个QuickProxy。

    登录网关脚本

    Dim WinHttpReq
    Set WinHttpReq = CreateObject(”WinHttp.WinHttpRequest.5.1″)
    WinHttpReq.Open “POST”, “http://nic.bjut.edu.cn/”,False
    WinHttpReq.Send “DDDDD=myid&upass=mypass&0MKKey=%C1%AC%BD%D3%CD%F8%C2%E7″
    ‘~ Wscript.Echo WinHttpReq.ResponseText

    退出脚本

    Dim WinHttpReq
    Set WinHttpReq = CreateObject(”WinHttp.WinHttpRequest.5.1″)
    WinHttpReq.Open “GET”, “http://nic.bjut.edu.cn/F.htm”,False
    WinHttpReq.Send
    ‘~ Wscript.Echo WinHttpReq.ResponseText

    其实就模拟了一下浏览器的行为,比较BS的是帐号密码都没有加密就发送了,MKKey那一长串值不知是何意,我是直接从Wireshark捕捉的包里拷出来的,我的Fiddler一打开系统就僵死掉了,所以只能用这个大家伙了。

    ruby版 for Linux

    require ‘net/http’
    h = Net::HTTP.new(’nic.bjut.edu.cn’, 80)
    h.post(’/',’DDDDD=s2007xxx&upass=520xxx&0MKKey=%C1%AC%BD%D3%CD%F8%C2%E7′)

    require ‘net/http’
    h = Net::HTTP.new(’nic.bjut.edu.cn’, 80)
    h.get(’/F.htm’)

    IE新窗口打开快捷方式

    五月 22nd, 2008

    [HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Main]
    新建一个名称为AllowWindowReuse的DWORD类型的值,赋为0

    快速打开注册表,保存为vbs

    Option Explicit
    Dim objShell
    Dim strRegAddress
    Set objShell = CreateObject(”Wscript.Shell”)
    ‘获取用户所输入的地址。
    strRegAddress = InputBox(”请输入注册表路径地址”, “注册表地址栏”)
    If strRegAddress = “” Then
    WScript.Quit
    End If
    ‘如果注册表编辑器已经运行则要先关闭它。
    If objShell.AppActivate(”注册表编辑器”) Then
    objShell.SendKeys(”%{F4}”) ‘Alt + F4关闭窗口。
    WScript.Sleep(1000) ‘等待注册表编辑器关闭。
    End If
    ‘合成最终的地址。
    strRegAddress = “我的电脑\” & strRegAddress
    ‘将该地址写入注册表。
    objShell.RegWrite “HKCU\Software\Microsoft\Windows\CurrentVersion\Applets\Regedit\LastKey”,strRegAddress
    ‘启动注册表编辑器。
    objShell.Run(”RegEdit.exe”)

    路径需要HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Main这样的完整路径,不能使用缩写。另外也可以用Systeminternal套件里的regjump。

    用EverNote 3.0 换下 OneNote

    四月 17th, 2008

    一直在找一款好用一点的笔记管理软件,这个信息泛滥的年代东记一点西记一点可不是一个好习惯。试过AutoHotKey+notepad和以前的EverNote最后还是觉得OneNote比较顺手。直到这次EverNote出了3.0版。

    首先在内容收集方面,它可以方便的截取IE和FireFox的上的内容。还有一个Universal Clipper可以通过剪切板来采集任何程序的文本图片。

    内容管理上,它支持标签。这个太喜欢了,有趣的东西总应该有很多面,因此固定的分类是很难的,而多加几个标签则是很容易的,而且更便于浏览了。

    另外还有针对图片的文字识别,瞬间过滤式的关键字搜索,手写涂鸦等比较新奇的功能。

    当然3.0最大的变化是引入了帐户,要使用EverNote必须先申请一个帐号,然后你所有的笔记都会被同步到EverNote的网站上。你甚至可以不安装EverNote的客户端,而只用网页版的EverNote。

    目前为止这些功能都是免费的,还有什么好说的呢,简直已经完美了。

    EverNote 3.0现在Beta测试中,需要邀请的请留言。

    Google toolbar一直是我的装机必备。而自定义按钮是它一个尤为有用的功能,这个小功能虽然简单却省了我不少时间,比如去图书馆查书、上射手网下字幕、以及查看Gmail邮件这些常用的操作现在都在鼠标一点间可以实现了,的确让人心情愉悦。但是美中不足的是对于这些非常个人化的信息Google并没有提供一个方法来备份,每次重装系统后我们都不得不重新去收集这些按钮,很不方便。这些信息无非就是一个Base16编码的图标和几个链接数据量非常小,完全可以存储到对应的Google帐号里,这样也可以鼓励大家登陆Google工具条增加产品粘合度。

    既然如此,我只好自己动手了。因为Toolbar的自定义按钮信息IE和FireFox是共享的,所以它们显然是存储在某个公共的位置或注册表里。打开Filemon和Regmon过滤关键字IEXPLORE.EXE并选上Log Opens,Log Writes,Log Successes。然后在IE里生成一个自定义按钮,比如用百度的搜索框:)查看*mon们的捕获结果,可以很快发现Toolbar把信息藏在了两个地方,一个是%USERPROFILE%\Local Settings\Application Data\Google\Custom Buttons存放着一些XML格式的文件。另一个在注册表位置HKEY_CURRENT_USER\Software\Google\Google Toolbar\4.0\Options\Custom Buttons上,是一些跟前面那些XML相关的信息。经过测试只要保存了这两处的信息,就可以成功恢复所有的自定义按钮。

    最后我写了一个脚本来自动执行以上操作。

    @echo===================================================
    @echo backup.bat 备份Google工具栏自定义按钮
    @echo ===================================================
    xcopy “%USERPROFILE%\Local Settings\Application Data\Google\Custom Buttons” %CD%\data\file /G /I /E /Q  /K
    REGEDIT /E %CD%\data\gtb.reg “HKEY_CURRENT_USER\Software\Google\Google Toolbar\4.0\Options\Custom Buttons”

    @echo=====================================================================
    @echo install.bat 恢复Google工具栏自定义按钮,同目录下要有运行backup.bat生成的data文件夹.
    @echo====================================================================
    xcopy “%CD%\data\file” “%USERPROFILE%\Local Settings\Application Data\Google\Custom Buttons”  /G /I /E /Q  /K
    REGEDIT  /s  /I “%CD%\data\gtb.reg”  “HKEY_CURRENT_USER\Software\Google\Google Toolbar\4.0\Options\Custom Buttons”

    http://cid-ffe377e867258d1b.skydrive.live.com/self.aspx/Public/gtoolbarbackup.zip