[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

[其他] 【第三方】CAPI 注入版【1.2 1D910】

第三方命令行工具 CAPI
让批处理调用API
Made By Defanive

11/04/12:更新1.2, Build 1D910, x32

目录
2L 开发手记
3L 第三方信息
4L 方法列表
5L 方法示例
6L 开发范例

http://bcn.bathome.net/s/tool/index.html?key=CAPI
3

评分人数

    • ht河豚: 体积小技术 + 1
    • cjiabing: 看到那精致的画面和流畅的运行我不由得激动 ...PB + 12 技术 + 3
    • cutebe: 才,6楼CPU占用也不高技术 + 1
第三方命令行工具编程
Http://Hi.Baidu.Com/Console_App

本帖最后由 defanive 于 2012-11-5 04:21 编辑

开发手记

在非注入版CAPI的开发完成后,很多人提到了非注入版的缺陷
由于调用API之后进程被销毁,很多在进程内保存信息的API都无法正常使用
而且由于频繁打开新进程,调用API的效率降低了很多

于是注入版CAPI就在开发当中了
经过几个星期的开发,大约在6月底完成了CAPI 1.0版的开发
后续进行了几次修改,加入了COM调用功能,版本号改为1.1
这就意味着,支持COM功能的CAPI可以调用DirectX8了,也就是可以用批处理开发DX游戏等
还未进行过DX的调用测试,但是理论上应该是可以的

然后就这样搁置了几个月在我电脑里面
现在快10月份了,终于决定,不管BUG有多少,先发布出来再说

由于是注入版的,所以本身只能适用于32位的操作系统
因为dll是32位代码,所以无法注入到64位的cmd.exe进程中
但是,批处理可以判断自己是否在64位系统中,然后启动32位的cmd.exe,这样CAPI也可以运行在64位的系统中
没有测试环境,无法确定是否运行正常

免杀问题实在没办法怎么做,cmd.exe属于非常敏感的系统进程,基本上注入都很危险
尽量做到最好了,基本不怎么杀(360就算了,跟360玩免杀毫无意义)
因此想使用这个的开发者们,自己斟酌使用,有被杀的风险

用CAPI进行开发,个人感觉更考验的是对API的理解
CAPI除了API调用和COM调用和一些简单功能以外,本身并不带有任何其他功能
因此如果对API使用不熟,用CAPI也没办法做出特别超群的东西

暂时是这样,先发布1.1 Build 1D861
BUG反馈,建议等会帮助CAPI前进

————————————————————————————————————————

关于API可调用的回调函数,例如EnumWindows的回调,窗口消息的回调函数,有一个想法
最近学业甚忙,等到有时间了就开始做
简单的来说就是CAPI虚拟一个回调函数,然后虚拟的回调函数调用批处理
如果做成了的话,批处理就可以彻底的开发窗口程序了
也可以使用SetWindowsHookEx里面的Lower-Level Hooks,做键盘钩子和鼠标钩子
总之一切需要用到回调函数的都可以使用了
原理可用性大致确定,稳定性尚不清楚,有待测试
如果做好了就是一大进步,做不好就只能想其他办法了

————————————————————————————————————————

杯具试了一下结果不行,暂时没什么可以做的了

————————————————————————————————————————

更新1.1, Build 1D8B0, x32
对Inline API Hook进行了改进,改用新的方法提高效率
现在5000条set命令的执行耗时和无CAPI注入的耗时相差在1毫秒以内
基本上已经不影响set命令的执行效率了
另外一个重要的BUG修正,Mem Put命令的@标识符,现在可以正常的移动指针了
API Call增加了.标识符,可以传字节参数(目的是兼容cdecl函数)
CAPI.dll大小缩小了0.50KB

————————————————————————————————————————

更新1.2, Build 1D910, x32
把CAPI的调用方式分成两类,SetCall和GetCall
SetCall为旧版的"set CAPI=命令"的调用方式
GetCall为"%CAPI 命令%"的调用方式
对API调用时的dll加载做了优化,dll加载后不进行卸载,加速下一次使用dll的速度
第三方命令行工具编程
Http://Hi.Baidu.Com/Console_App

TOP

本帖最后由 defanive 于 2012-11-5 04:24 编辑

第三方信息

CAPI.dll
1.2 Build 1D910 x32
8.00KB

CAPI.exe
2.29KB

在批处理开头需要调用一次CAPI.exe(无参数),同时CAPI.dll和CAPI.exe必须在同一目录下
调用完之后会将CAPI.dll注入到cmd.exe进程中
CAPI支持两种调用方法,GetCall和SetCall
默认情况下SetCall处于开启状态,GetCall处于关闭状态
SetCall调用方法是用set命令修改CAPI变量值完成的,如set "CAPI=Mem Alloc 8"
GetCall调用方法是用%(或!)查询变量名完成的,如%CAPI Mem Alloc 8%
CAPI_Ret变量储存执行的返回值
CAPI_Err变量储存调用API后GetLastError的返回值
这两个变量的内容请在命令执行完之后及时复制到其他变量
在GetCall中命令的变量会被解析成CAPI_Ret的值

注入版的最大优势在于只需要批处理开头调用一次CAPI.exe,往后任何调用都可以通过set命令完成
这样提高了CAPI的调用速度,同时让代码执行在cmd.exe进程中

现在最新的1.2版本支持GetCall的调用方式,更加接近于函数调用的语法
如开启GetCall后,代码echo %CAPI CAPIDll Ver%
就会先执行CAPI CAPIDll Ver,并把返回值作为变量值,实际执行了echo 1.2
第三方命令行工具编程
Http://Hi.Baidu.Com/Console_App

TOP

[i=s] 本帖最后由 defanive 于 2012-11-5 04:25 编辑 [/i]

[b]命令列表[/b]

前置符号及意义:
.        1B        字节
:        2B        短整型
;        4B        长整型
#        -        字符串(ANSI)
$        -        字符串(Unicode)
*        4B        变量(的地址)
@        0B        移动指针,后跟欲移动的距离

这些前置符号往往用在参数里面,用于指定参数的类型和意义

接下来就是CAPI支持的命令列表:

Mem Alloc [sz]
在cmd.exe进程里面创建一块内存
注意,内存块使用完毕后需调用Mem Free释放,否则可能造成内存泄漏
参数:[sz]为欲创建的大小
返回值:创建的内存块的地址保存在CAPI_Ret变量里

Mem Free [addr]
释放cmd.exe进程里面的一块内存
注意,不要释放非自己创建的内存块,可能造成cmd.exe崩溃
参数:[addr]为欲释放的内存地址
返回值:无

Mem Put [s][addr] [s][data] [s][data] ...
将数据按格式写入内存地址中
注意,如果写入的数据量超过内存块大小,可能造成cmd.exe崩溃
参数:[s][addr]为欲写入内存地址,可以用“;内存地址”或者“*变量名”;[s][data]为欲写入的数据,[s]为前置符号,[data]为数据内容
返回值:无

Mem Copy [s][addr] [s][addr] [sz]
将源地址的一段内存复制到目标地址
注意,如果地址不可读或不可写,可能造成cmd.exe崩溃
参数:第一个参数[s][addr]为目标地址,第二个为源地址,都可以用“;内存地址”或者“*变量名”;[sz]为欲复制的内存块大小
返回值:无

Mem Print [s][addr] [s][var] [s][var] ...
将内存地址处的数据输出
注意,如果输出的数据量超过内存块的大小,可能造成cmd.exe崩溃
参数:[s][addr]为内存地址,可以用“;内存地址”或者“*变量名”,[s][var]为输出参数,[s]为输出的数据类型,[var]为输出的目标变量名
返回值:无

Var Fill [var] [char] [sz]
将变量填充为指定数量个指定字符
参数:[var]为目标变量名,[char]为字符,[sz]为字符数量
返回值:无

Var LenW [var]
返回变量的Unicode长度
参数:[var]为变量名
返回值:长度保存在CAPI_Ret变量里

Var LenA [var]
返回变量的ANSI长度
参数:[var]为变量名
返回值:长度保存在CAPI_Ret变量里

Var GetCall [Enable/Disable]
开启或关闭GetCall调用方式
参数:Enable或Disable
返回值:无

Var SetCall [Enable/Disable]
开启或关闭SetCall调用方式
参数:Enable或Disable
返回值:无

API Call [dll] [API] [s][data] [s][data] ...
调用API
参数:[dll]为dll路径,[API]为API函数全名,[s][data]为参数,[s]为参数标识(仅.;#$*可用),[data]为参数数据
返回值:API执行的返回值保存在CAPI_Ret变量里,API执行后的GetLastError返回值保存在CAPI_Err变量里

COM Init
初始化COM调用
注意,进行任何COM操作前必须调用本操作
参数:无
返回值:无

COM Create [data]
创建一个COM对象实例
注意,创建的对象实例在不需要使用时必须用COM Release释放
参数:[data]为COM对象名称
返回值:对象实例地址保存在CAPI_Ret变量里

COM Release [addr]
释放指定地址的对象实例
注意,创建任何对象之后都需要将对象释放;若对已释放的对象进行操作会导致cmd.exe崩溃
参数:[addr]为对象实例地址
返回值:无

COM Method [addr] [name] [s][data] [s][data] ...
调用对象实例的方法
参数:[addr]为对象实例地址,[name]为方法名称,[s][data]为参数,[s]为参数标识(仅;$可用),[data]为参数
返回值:方法的返回值保存在CAPI_Ret变量中

COM Get [addr] [name]
获取对象实例的属性
参数:[addr]为对象实例地址,[name]为属性名称
返回值:属性的值保存在CAPI_Ret变量中

COM Put [addr] [name] [s][data]
赋值对象实例的属性
参数:[addr]为对象实例地址,[name]为属性名称,[s][data]为数据,[s]为数据标识(仅;$可用),[data]为数据
返回值:无

CAPIDll Ver
获取CAPI.dll的版本号
参数:无
返回值:版本号保存在CAPI_Ret变量中

CAPIDll /?
打印CAPI.dll的信息
参数:无
返回值:无
第三方命令行工具编程
Http://Hi.Baidu.Com/Console_App

TOP

本帖最后由 defanive 于 2012-11-5 04:25 编辑

方法示例

Mem Alloc与Free:
@echo off
CAPI
set "CAPI=Mem Alloc 4"
set "lpAddress=%CAPI_Ret%"
echo %lpAddress%
pause
set "CAPI=Mem Free %lpAddress%"
pause
创建了一块大小为4的内存,内存地址保存在lpAddress里
在批处理第一次暂停时,使用工具查看cmd.exe内存,可以看到在输出的地址处为4个空白字节的内存,第二次pause时,可以看到内存已经被释放

Mem Put:
@echo off
CAPI
set var=hello
set data=0123456789
set "CAPI=Mem Put *data .97 @1 :25105 #ab $ab *var"
echo %data%
pause
执行前data变量的内存内容为30 00 31 00 32 00 33 00 34 00 35 00 36 00 37 00 38 00 39 00
执行写入命令时,此时指针指向第1个字节,.97将1个字节为97写入,于是变成了61 00 31 00 ...,指针后移1位,指向第2个字节
@1将指针后移1位,此时指针指向第3个字节
:25105,此时指针指向第3个字节,将2个字节为25105写入,于是变成了61 00 62 11 32 00 ...,指针后移2位
#ab,此时指针指向第5位,将2个字节的ANSI字符串ab写入,于是变成了61 00 62 11 61 62 33 00 34 00 ...,指针后移2位
$ab,此时指针指向第7位,将4个字节的Unicode字符串ab写入,于是变成了61 00 62 11 61 62 61 00 62 00 ...,指针后移4位
*var,此时指针指向第11位,将var变量的内容全部写入

Mem Copy:
@echo off
CAPI
set var=hello
set data=0123456789
set "CAPI=Mem Copy *data *var 6"
echo %data%
pause
执行时,将var变量的前4个字节复制到data变量中,即是“hel”
因此输出“hel3456789”

Mem Print:
@echo off
CAPI
set var=0123456
set "CAPI=Mem Print *var .output_1 @2 :output_2 @1 #output_3 $output_4"
set output_
pause
var变量的内容为30 00 31 00 32 00 33 00 34 00 35 00 36 00
.output_1,此时指向第1个字节,将1字节的内容“31”放入output_1变量中,也就是48
@2,此时指针指向第2个字节,将指针后移2位,此时指针指向第4个字节
:output_2,此时指针指向第4个字节,将2字节的内容“00 32”放入output_2变量中,也就是12800
@1,此时指针指向第6个字节,将指针后移1位,此时指针指向第7个字节
#output_3,此时指针指向第7个字节,将接下来的内容作为ANSI字符串放入output_3变量中,也就是“33”,字符串3
$output_4,此时指针指向第9个字节,将接下来的内容作为Unicode字符串放入output_4变量中,也就是“34 00 35 00 36 00”,字符串456

Var Fill:
@echo off
CAPI
set data=test
set "CAPI=Var Fill data a 10"
echo %data%
pause
将data变量的内容以10个a覆盖,输出aaaaaaaaaa

Var LenW与LenA:
@echo off
CAPI
set data=我是Defanive
set "CAPI=Var LenW data"
echo %CAPI_Ret%
set "CAPI=Var LenA data"
echo %CAPI_Ret%
pause
LenW返回data变量的Unicode长度,也就是10
LenA返回data变量的ANSI长度,也就是12

API Call:
@echo off
CAPI
set "data=message"
set "CAPI=API Call user32 MessageBoxW ;0 *data $title ;1"
echo %CAPI_Ret%
pause
调用API MessageBox,第一个参数为0,第二个参数为data变量的地址,第三个参数为Unicode字符串title,第四个参数为1
由于CMD内部将变量data储存为Unicode,因此应使用Unicode版本的API,也就是MessageBoxW

COM(1):
@echo off
CAPI
set CAPI=COM Init
set CAPI=COM Create sapi.spvoice
set objSP=%CAPI_Ret%
set CAPI=Com Put %objSP% Rate ;5
set CAPI=Com Get %objSP% Volume
echo %CAPI_Ret%
set CAPI=Com Method %objSP% Speak $hello ;0
set CAPI=Com Release %objSP%
pause
等价于以下vbs代码
Set objSP=CreateObject("sapi.spvoice")
objSP.Rate=5
MsgBox objSP.Volume
objSP.Speak "hello",0
Set objSP=nothing

COM(2):
@echo off
CAPI
set CAPI=COM Init
set CAPI=COM Create scripting.filesystemobject
set objFSO=%CAPI_Ret%
set CAPI=COM Method %objFSO% OpenTextFile $1.txt ;1
set objTS=%CAPI_Ret%
set CAPI=COM Method %objTS% Skip ;2
set CAPI=COM Method %objTS% ReadLine
echo %CAPI_Ret%
set CAPI=COM Release %objTS%
set CAPI=COM Release %objFSO%
pause
等价于以下vbs代码
Set objFSO=CreateObject("scripting.filesystemobject")
Set objTS=objFSO.OpenTextFile("1.txt",1)
objTS.Skip 2
MsgBox objTS.ReadLine
set objTS=Nothing
set objFSO=Nothing

GetCall:
@echo off
CAPI
set CAPI=Var GetCall Enable
echo %CAPI CAPIDll Ver%
pause
等价于以下的SetCall调用代码:
@echo off
CAPI
set CAPI=CAPIDll Ver
echo %CAPI_Ret%
pause
第三方命令行工具编程
Http://Hi.Baidu.Com/Console_App

TOP

开发范例

Dodge 躲避球
由于进程数据得以保存,我们现在可以进行非常完美的画面显示了
同时画面也可以达到很高的FPS
1

评分人数

第三方命令行工具编程
Http://Hi.Baidu.Com/Console_App

TOP

占楼待编辑
第三方命令行工具编程
Http://Hi.Baidu.Com/Console_App

TOP

回复 11# wc726842270
API的话对于是不是解释性语言都是很大用处的
COM的话相信经常在VBS中用COM的同学都知道其强大
第三方命令行工具编程
Http://Hi.Baidu.Com/Console_App

TOP

回复 12# tms2010
暂时没有兼容Win8的打算
第三方命令行工具编程
Http://Hi.Baidu.Com/Console_App

TOP

回复 13# 3dnowex
理论上是可以兼容x64的,批处理只需要判断自己是在x64环境下运行,然后启动32位的cmd.exe就可以正常执行了
没有测试环境暂时无法验证
第三方命令行工具编程
Http://Hi.Baidu.Com/Console_App

TOP

回复 18# netbenton
其实按照大部分机器的运行速度FPS都可以达到100以上的(我的机子经常都是300多)
于是加入了FPS限制,把FPS限制在30左右
但是由于sleep的精度有限,有最小延迟,所以按照计算出来的结果慢的机器可能实际FPS在20左右
总之这部分是程序设计的问题,与CAPI效率没什么关系,CAPI速度是比一般的第三方调用快很多倍的

关于杀软的问题,金山我在做免杀的时候也注意到了
据说金山除了静态查杀还有动态的,动态查杀要过很难(像什么沙盒执行什么的就更加难过了)
所以金山大概以我个人的力量还暂时过不了,毕竟我只会码程序,免杀这些也就是知道点皮毛
总之杀软的问题,还是没什么解决方案,只能说“开发者斟酌使用”了
第三方命令行工具编程
Http://Hi.Baidu.Com/Console_App

TOP

回复 20# cutebe
没画面的应该是注入失败了
试一下在那台电脑上打开CMD,进入到CAPI的目录
然后执行CAPI,再执行set CAPI=CAPIDll /?
看一下有没有显示帮助信息
第三方命令行工具编程
Http://Hi.Baidu.Com/Console_App

TOP

回复 22# cutebe
没留意过我的文档的问题。。
第三方命令行工具编程
Http://Hi.Baidu.Com/Console_App

TOP

回复 27# netbenton
我给你的那个去掉FPS限制的版本怎么样?
PS 貌似AMD都比较慢?我不是很清楚。。
第三方命令行工具编程
Http://Hi.Baidu.Com/Console_App

TOP

回复 29# garyng
不是,是Hook了SetEnvironmentVariable,所以每次set命令的时候都会执行我的函数,如果变量名是CAPI的话就会进行处理
第三方命令行工具编程
Http://Hi.Baidu.Com/Console_App

TOP

返回列表