打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
API HOOK 实战解决War FTP无法重命名覆盖已经存在文件的有关问题之最终篇

API HOOK 实战解决War FTP无法重命名覆盖已经存在文件的有关问题之最终篇

www.MyException.Cn   发布于:2012-08-03 00:12:14   浏览:15次
API HOOK 实战解决War FTP无法重命名覆盖已经存在文件的问题之最终篇

看过这个系列的朋友一定都会发现,两种方法都存在着缺憾,如果只是用于普通环境也罢,但我编写此程序的目的是要用于windows 2003的服务器生产环境的,没有达到理想前都不可能轻易部署上去。

由于AutoIt3的版主不太可能再写一次hook的代码,于是只好继续研究Deviare组件。

之前碰到的问题是用VB调用时速度偏慢,而且CPU占用比较高。在Deviare的论坛上逛时,发现还可以用VBScript来编写,于是将我原来的代码稍微进行了修改。然后我惊奇地发现VBScript调用Deviare组件进行Hook时,速度和AutoIt3几乎相同,而且CPU也恢复正常了!

于是我在Deviare论坛发问,得到的答复是由于VB 6.0的单线程设计架构,导致在处理事件时会出现一些问题。

看来继续使用VB 6.0是无法完成了,那么我该用何种语言完成呢?

我的程序需要完成如下目标:

1、能够Hook以系统服务运行的war-ftpd.exe进程的CreateFileW函数,并修改相关的参数值;

2、程序要以GUI方式运行,不能用CUI方式运行;


要能够完成第1点,目前只能使用Deviare组件。

要能够完成第2点,VBScript语言是做不到,至少做起来相当麻烦。

Deviare论坛版主,在给我的问题进行答复后没有多久,更新了Deviare组件版本到2.0.6.在其中我发现example目录增加了一些内容,除了原来的C#的例子,又增加了VBScript和Python的例子。于是我开始了Python的研究之路。

Python说实话是一个相当不错的语言,各种库函数都相当丰富。根据版主提供的Python例子,我很快就编写好了CUI的版本。

但在研究Python编写GUI程序时,我还是碰壁不少。先后研究了Python自带的Tkinter和wxpython,但发现这些GUI库对于事件的处理似乎与VB还是有点不同,搞了几天也没有弄出个啥。

我当然可以继续静下心来研究Python,并最终完成第2点目标,但我不知道会要多久,我不可能一直在这个问题上面耗下去。

碰巧,在研究Python时,偶然在某个帖子看到有人讨论到了FreeBasic程序如何转换为Python。于是我开始关注了FreeBasic。不看不知道,一看吓一跳。原来世界上除了VB之外还有那么多Basic的产品存在,而且似乎都在某些方面要远远好于VB 6.0.

我从中挑选了几个比较有名的开始研究,先后看过FreeBasic、PowerBasic、RealBasic,这些软件要实现GUI我觉得问题都不大,但用起来都没有VB那么方便,另外在使用COM组件时,显然离VB还是有不小的差距。所以说为什么VB能成为Basic事实上的标准,是有它的道理的。微软的亲生儿子怎么也不会比其它要差吧?

在辗转反侧之间,又是几周过去了。想想也真是沮丧,如果当初把VC学好,把Windows编程学精,那么我何至于如此呢?但世界上的问题那么多,我也不可能有那么多精力去一一研究仔细,尽量使用现成的东西,尽量踩在前人的肩膀上,那才是我们应该学习的。

在各种编程语言中挑选时,我突然想到了“快手——aauto”。这个语言作者最初是写按键精灵的,后来开发了更强大的aauto语言。我以前在研究AutoIt之前实际上研究过aauto,只是后来由于其它原因中断了。于是我赶快把抛弃的aauto捡起来,发现要实现我的目标还真是简单。

用来大概2天时间,我完成了我的目标,另外增加了其它的一些功能,完善了我的程序。程序代码如下:

 

import win.ui;
import win.util.tray;
import win.ui.menu;
import com.picture;
import com;
import process;
import mouse;
import win.ui.atom;

                
/*DSG{{*/
mainForm = ..win.form( right=600;bottom=400;parent=...;text=
"WarFTP参数拦截程序";max=false )
mainForm.add( 
listview={ bgcolor=16777215;bottom=380;right=573;left=26;top=18;z=1;vscroll=1;fullRow=1;edge=1;cls=
"listview" }
)
/*}}*/

/*listviewColorize{{*/
import util;

listviewColorize = (
function () {
    
var NMLVCUSTOMDRAW = class {
        struct nmcd = {
            struct hdr = ..win.ui.NMHDR();
            INT dwDrawStage;
            pointer hdc;
            struct rc = ::RECT();
            int dwItemSpec;
            INT uItemState;
            int lItemlParam;
        };
        INT clrText;
        INT clrTextBk;
        int iSubItem;
        INT dwItemType;
        INT clrFace;
        int iIconEffect;
        int iIconPhase;
        int iPartId;
        int iStateId;
        struct rcText = ::RECT();
        INT uAlign;
    }
    
    
return function (listview) {
        listview._colors = ..table.array(listview.count, 0);
        
        listview.onnotify = 
function (id,code,ptr) {
            
if (code === 0xFFFFFFF4/*_NM_CUSTOMDRAW*/) {
                
var nmlvcd = NMLVCUSTOMDRAW();
                raw.convert(ptr, nmlvcd);
                
                
select (nmlvcd.nmcd.dwDrawStage) {
                    
case 0x1/*_CDDS_PREPAINT*/
                        
return 0x20/*_CDRF_NOTIFYITEMDRAW*/
                    
case 0x10001/*_CDDS_ITEMPREPAINT*/ {
                        raw.mixin(ptr, nmlvcd, { clrText = 
owner._colors[nmlvcd.nmcd.dwItemSpec + 1] });
                        
return 0/*_CDRF_DODEFAULT*/;
                    }
                }
            }
        }
        
        listview.setItemColor = 
function (item, col) {
            
owner._colors[item] = col;
        }
        
        listview.addItem = ..util.connect(listview, listview.addItem,
            
function (text, ind, ...) {
                
if (ind)
                    ..table.insert(
owner._colors, 0, ind);
                
else
                    ..table.push(
owner._colors, 0);
            }
        );
        
        listview.delItem = ..util.connect(listview, listview.delItem,
            
function (item) {
                ..table.remove(
owner._colors, item);
            }
        );
    }
})();
/*}}*/

var atom,hwnd/*冲突窗口的句柄,该函数会自动激活此窗口*/ = mainForm.atom("6D949DCA-7233-46D3-B55A-9E1B2FC758C6");
if(!atom){
    
/*为窗口设置原子值可以避免一个程序重复运行多个实例*/
    win.quitMessage()
    
return
}

listviewColorize(mainForm.listview);

var spyMgr
var processName="war-ftpd.exe"
var serviceName = "WARSVR"
var myHook,event_handler,spyMgr_events

EmptyWorkingSet := ::Psapi.api(
"EmptyWorkingSet","bool(pointer handle)")
emptymem=
function(){
    
var handle = process.OpenProcess(0x1f0fff,false,process.getId())
    EmptyWorkingSet(handle)
    raw.closehandle(handle)
}

//在listview写日志
//flag=0 —— 正常日志
//flag=1 —— 错误日志
function writelog(msg,flag=0){
    
if(mainForm.listview.count>5000){
        mainForm.listview.clear()
    }
    
    
var item = mainForm.listview.addItem({tostring(time());msg})
    
if( flag == 1 ){ 
        mainForm.listview.setItemColor(item, 0x0000FF)  
    }
    
    mainForm.listview.ensureVisible(mainForm.listview.count)    
    mainForm.listview.redraw()  
    
return  
}

//检查进程
function CheckProcess(processName) {
    
var objWMIService,colProcessList,objProcess
    
var strComputer
    
var pCount

    strComputer = 
"."

    objWMIService = com.GetObject(
"winmgmts:{impersonationLevel=impersonate}!\\" ++ strComputer ++ "\root\cimv2"
    colProcessList = objWMIService.ExecQuery(
"SELECT * FROM Win32_Process WHERE Name='" ++ processName ++ "'")  
    
    pCount = colProcessList.Count
    
    
if(pCount > 1) {
        
return -1
    }
    
elseif(pCount == 0) {
        
return -2
    }
    
elseif(pCount == 1) {
        
return -3
    }
}

//结束进程
function KillProcess(processName) {
    
var objWMIService,colProcessList,objProcess
    
var strComputer
    
    strComputer = 
"."

    objWMIService = com.GetObject(
"winmgmts:{impersonationLevel=impersonate}!\\" ++ strComputer ++ "\root\cimv2"
    colProcessList = objWMIService.ExecQuery(
"SELECT * FROM Win32_Process WHERE Name='" ++ processName ++ "'")  
    
    
for(i,objProcess in com.each(colProcessList)){
        objProcess.Terminate()  
    }   
}

//结束服务
function StopService(serviceName) {
    
var objWMIService,colServiceList,objService
    
var strComputer
    
var iStatus
    
    strComputer = 
"."

    objWMIService = com.GetObject(
"winmgmts:{impersonationLevel=impersonate}!\\" ++ strComputer ++ "\root\cimv2"
    colServiceList = objWMIService.ExecQuery(
"SELECT * FROM Win32_Service WHERE Name='" ++ serviceName ++ "'")  
    
    
for(i, objService in com.each(colServiceList)) {
        
if (objService.started == true) {
            iStatus = objService.StopService()
            
            
//等待10秒钟以便结束服务
            //sleep(10000)
            win.delay(10000)
            
if( iStatus != 0 ) {
                writelog(
"停止服务【" ++ serviceName ++ "】失败")
                
return false 
            }
            
else {
                writelog(
"成功停止服务【" ++ serviceName ++ "】")
                
return true   
            }
        }
        
else {
            writelog(
"服务【" ++ serviceName ++ "】未启动")
            
return true  
        }
    }
}

//启动服务
function StartService(serviceName) {
    
var objWMIService,colServiceList,objService
    
var strComputer
    
var iStatus
    
    strComputer = 
"."

    objWMIService = com.GetObject(
"winmgmts:{impersonationLevel=impersonate}!\\" ++ strComputer ++ "\root\cimv2"
    colServiceList = objWMIService.ExecQuery(
"SELECT * FROM Win32_Service WHERE Name='" ++ serviceName ++ "'")  
    
    
for(i, objService in com.each(colServiceList)) {
        
if (tonumber(objService.started) == false) {
            iStatus = objService.StartService()
            
            
//等待10秒钟以便启动服务
            //sleep(10000)
            win.delay(10000)
            
if( iStatus != 0 ) {
                writelog(
"启动服务【" ++ serviceName ++ "】失败")
                
return false 
            }
            
else {
                writelog(
"成功启动服务【" ++ serviceName ++ "】")
                
return true   
            }
        }
        
else {
            writelog(
"服务【" ++ serviceName ++ "】已经启动")
            
return true  
        }
    }       
}

//*********************************************************主程序开始************************************************************************
RegisterWindowMessage := ::User32.api( "RegisterWindowMessageA""Long(String lpString)");
msgTaskbarRestart = RegisterWindowMessage(
"TaskbarCreated")

tray = win.util.tray(mainForm,130) 
//创建托盘图标
tray.message = 0x400+9981/*_WM_TRAYMESSAGE*/
tray.tip = 
"WarFTP参数拦截程序" //设置鼠标提示 

popmenu = win.ui.popmenu(mainForm)
popmenu.add(
'隐藏',function(id){
    stat = win.isVisible(mainForm.hwnd)
    
if(stat){
        mainForm.show(
false);
        popmenu.setString(1,
"显示")    
    }
    
else {
        mainForm.show(
true)
        popmenu.setString(1,
"隐藏")
    }   
})
popmenu.add()
//分隔线
popmenu.add('退出',function(id){ 
    mainForm.close() 
})

mainForm.wndproc = 
function(hwnd,message,wParam,lParam){

    
select(message) {//判断消息类型
        case (0x10/*_WM_CLOSE*/){
            
//询问是否退出
            var ok = mainForm.msgboxTest("退出此程序将导致WarFTP出现问题,请确认是否退出?","确认信息")
            
if(ok == false){
                
return wParam
            }
            tray.delete()
        }
        
case( 0x400+9981/*_WM_TRAYMESSAGE*/ ) { //托盘图标消息
            try{
                
//右键单击弹出菜单  
                if( lParam == 0x205/*_WM_RBUTTONUP*/ ){
                    x,y = mouse.getPos()
                    
                    
//弹出托盘菜单以前,一定要前置主窗口中,不然不点击菜单不会消失
                    win.setForeground(mainForm.hwnd)
                    popmenu.popup( x,y,
true )
                }   
                
                
//左键双击
                if(lParam == 0x203/*_WM_LBUTTONDBLCLK)*/){
                    stat = win.isVisible(mainForm.hwnd)
                    
if(stat){
                        mainForm.show(
false)
                        popmenu.setString(1,
"显示"
                        tray.pop(
"程序隐藏到系统托盘","程序提示")   
                    }
                    
else {
                        mainForm.show(
true)
                        popmenu.setString(1,
"隐藏")
                    }
                }
            }
            
catch(e){
                writelog(
"错误信息:" ++ e,1)
            }   
            
            
        } 
        
case( 0x112/*_WM_SYSCOMMAND*/ ){ //系统命令消息
            if( wParam == 0xF020/*_SC_MINIMIZE*/ ){ //用户点击了最小化按钮
                
                
//import win.util.tray
                //tray = win.util.tray(mainForm) //创建托盘图标 
                tray.pop("程序隐藏到系统托盘","程序提示")
                mainForm.show(
false//隐藏窗口
                popmenu.setString(1,"显示")
                emptymem()      
//释放内存
                return true//阻击默认消息传递,取消最小化过程
            } 
        }
        
case(msgTaskbarRestart){    //任务栏重建
            //win.util.tray.Shell_NotifyIcon(0x0/*_NIM_ADD*/,tray.m_tnd)
            //writelog("系统托盘重建")
            tray.reset()
        }
    }
    
    
//无返回值则继续调用默认回调函数
}



 

//增加listview的列
mainForm.listview.insertColumn("时间",120)
mainForm.listview.insertColumn(
"信息",-1)

//让主窗口先显示,以便在listview输出内容
mainForm.show( true )

writelog(
"程序启动")

//查找是否存在 war-ftpd.exe 进程
lPID = CheckProcess(processName)
if(lPID == -1) { 
    writelog(
"找到多个【" ++ processName ++ "】进程")
    writelog(
"结束【" ++ processName ++ "】进程...")
    KillProcess(processName)         
    
//sleep(1000)
    win.delay(1000)
  }
elseif( lPID == -2) {
    writelog(
"未找到【" ++ processName ++ "】进程")
 }
elseif( lPID == -3) {
    writelog(
"找到1个【" ++ processName ++ "】进程")
    writelog(
"结束【" ++ processName ++ "】对应的服务程序...")
    StopService(serviceName)    
}

writelog(
"启动【" ++ processName ++ "】对应的服务程序...")
StartService(serviceName)

writelog(
"开始创建DeviareCom组件...")
spyMgr = com.CreateObject(
"DeviareCOM.NktSpyMgr"
spyMgr.DatabasePath = 
""
spyMgr.AgentPath = 
""
spyMgr.Initialize()
writelog(
"DeviareCom组件创建完毕")

lPID = spyMgr.FindProcessId(processName)
if(lPID == 0){
    writelog(
"未找到【" ++ processName ++ "】进程",1)
    mainForm.msgboxErr(
"未找到【" ++ processName ++ "】进程","错误")    
    mainForm.close()
}
else {
    writelog(
"【" ++ processName ++ "】进程PID:"  ++ tostring(lPID))
}


writelog(
"开始Hook【" ++ processName ++ "】的 kernel32.dll!CreateFileW 函数..." )
myHook = spyMgr.CreateHook(
"kernel32.dll!CreateFileW", 0) 
myHook.Attach(lPID,
true)
myHook.Hook(
true)

//sleep(2000)
win.delay(2000)

iftonumber(myHook.State(lPID)) == 2 ){ 
    writelog(
"Hook成功")
    emptymem()      
//释放内存
}
else
    writelog(
"Hook未成功,状态为:" ++ tostring(myHook.State(lPID)),1)
    mainForm.msgboxErr(
"Hook未成功","错误"
    mainForm.close()    
}




//注册事件
spyMgr_events = {
    OnFunctionCalled = 
function(hook, proc, callInfo) {
        
var paramEnum,param1,param4
        
//writelog("Function called: " ++ hook.FunctionName ++ " within process " ++ proc.Path ++ " " ++ callInfo.ToString())
        paramEnum = callInfo.Params()
        param1 = paramEnum.GetAt(0)
        param4 = paramEnum.GetAt(4)
        
        
        
iftonumber(param4.LongVal) == 1 ){ 
            
//writelog("发现要修改的参数值")
            if( callInfo.IsPreCall == true ){ 
                writelog(
tostring(param1.Value))
                param4.LongVal = 2
            }
        }               
    }
}
res, cookie = com.Connect(spyMgr, spyMgr_events)


/***
import config;
mainForm.bindConfig( config.mainForm,{
    edit = "text"; //绑定edit控件的text属性值到配置文件
    radiobutton = "checked";
    checkbox = "checked";
    combobox = "selIndex";
} );
***/



win.loopMessage(); 

 


 

至此,我的最初目标已经可以完美的实现。我也不想再花更多精力放在此问题上面。

经过我的几天测试,我的程序运行稳定,唯一的小缺憾是Deviare组件加载时会加载API的描述数据库,占用大概90M的内存。

Deviare版主答复说以后版本会增加一个可以减少数据库的版本,以减少内存占用。


如果将来有时间有精力的话,我希望用某种语言,使用原始代码直接完成我的目标。

不过这是将来的事情了,现在我已经满足了。


本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
[转贴]AU3-实用脚本大全
把数据库查询结果给table再显示到listview问题的解决
命令查看服务器SN号
如何获得故障设备的列表?
ghost后自动修改IP和计算机名的VBS脚本
通过组策略自动给客户机添加网络打印机
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服