找回密码
 注册
搜索
[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
查看: 34670|回复: 16

[其他] ICMD64版32版发布

[复制链接]
发表于 2021-9-25 02:48:50 | 显示全部楼层 |阅读模式
本帖最后由 slimay 于 2021-9-29 18:10 编辑
完美解决了64位dll的call问题, 同时具备非常接近C风格的书写语法
下载地址: http://cmd1152.ys168.com/  文件区  icmd3264版.zip
         ( 网盘文件随时消失, 只发一次, 错过了就别要了 )

ICMD注入版发布, 此次发布的是ICMD32以及ICMD64注入版, 兼容全部win系统.ICMD64可以完美
调用64位dll函数功能非常强大, 独有函数缓存机制, 远超capi. 32位, 64位dll通吃, 用到了
多项新技术整合.非常完善的类C语法整合, 一次load多个dll, 非常智能的语法书写体验.

COPYRIGHT@2021~2099 REWRITE BY SLIMAY, VERSION 1.0
ICMD64 注入版[使用手册]


用法:
首先在批处理中, 仅需调用一次如下命令: ICMD [要注入的 DLL文件名]
ICMD ICMD64.DLL

也可以在批处理脚本开头, 加入icmd的调用头
32位调用头为:
@if ["%1"]==[""] (if exist "%windir%\syswow64\cmd.exe" (start %windir%\syswow64\cmd.exe /c "%~f0" 1&exit))
@icmd32

64位调用头为:
@icmd64


然后基本语法同CMD.EXE,主要区别在于SET增加了 *开关
原生API调用开关 SET *

SET *[返回值]=[函数名] [参数] [参数] ...


示例:
REM 普通文本字串前加A作为标识,宽字符字串前加L。如 L"1.ico"标识宽字符的 "1.ico",其他类型无需任何标
    识, 也可以加 I整型, D高精度浮点, '字符'字符型, L'字符'宽字符型。宽字符串类型L, ANSI字符串类型A

REM 一次载入 所有DLL
set *= ILOAD    L"USER32.DLL"     L"KERNEL32.DLL"     L"GDI32.DLL"      L"GDIPLUS.DLL"        L"MSVCRT.DLL"

set *hIcon = LoadImageW 0 L"1.ico" 1 0 0 16
set *hCMD  = GetConsoleWindow
set *hDC   = GetDC %hCMD%
set *      = DrawIconEx %hDC% %x% 0 %hIcon% 128 128 0 0 3


内建函数:(备注: 5个内建函数 均为宽字符版本, 字符串参数均需要加 L 前缀 )
REM 载入DLL的命令, 如载入 DLL1, DLL2, DLL3
ILOAD [DLL1] [DLL1] [DLL3] ...

REM 填充一段内存空间, 按 FORMAT 给出的指定格式 如"*1*2*4+8*S" 按 1字节, 2字节, 4字节, 指针+8, 字符串型 填充 PTR地址空间, 后边的ARG... 就是填充的 对应类型数据
IFILL [PTR] [FORMAT] [ARG1] [ARG2] [ARG3] ...

REM 将一段内存空间的数据, 按 FORMAT 给出的指定格式 如"*1*2*4+8*S" 按 1字节, 2字节, 4字节, 指针+8, 字符串型 输出到 后边对应的VAR...变量名中
IOUT  [PTR] [FORMAT] [VAR1] [VAR2] [VAR3] ...

REM 将指定参数ARG... 按FORMAT格式 打印到 VAR变量名中 类似C语言中的sprintf
ISET [VAR] [FORMAT] [ARG1] [ARG2] [ARG3] ...

REM 将指定参数ARG... 按FORMAT格式 打印到 PTR地址空间 等同C语言中的sprintf
ISPR [PTR] [FORMAT] [ARG1] [ARG2] [ARG3] ...

备注: 5个内建函数 均为宽字符版本, 字符串参数均需要加 L 前缀


核心64位,32位汇编源码: (一直开源, 从不保留,方便他人研究,只因论坛限制字数, 只能贴这点最核心的了)


  1. // FunCall 汇编函数
  2. #ifdef  _WIN64
  3.         /*
  4.                 ;64位汇编 仅在单独的asm文件中方可编译, 不能内联
  5.                 ;intptr_t  FunCall64( void* hProc, intptr_t* DLLParam, int DLLParamNum, int needINT )
  6.                 ;CALL 64 APL, MADE BY SLIMAY 2021.09.24

  7.                 .CODE
  8.                 FunCall64 PROC
  9.                         ;  函数地址     传参数组     传参数目     传参模式
  10.                         ;intptr_t* hProc, void* DLLParam, int DLLParamNum, int needINT

  11.                         ;先备份传入的参数值
  12.                         mov        qword ptr [rsp +20h],  r9
  13.                         mov        qword ptr [rsp +18h],  r8  
  14.                         mov        qword ptr [rsp +10h],  rdx
  15.                         mov        qword ptr [rsp + 8h],  rcx

  16.                         ;寄存器原始值入栈
  17.                         push                rdi
  18.                         push                rbx
  19.                         ;栈指针备份
  20.                         mov        rdi, rsp

  21.                         ;设定快速传参栈空间(下移5个int64空间, 16字节对齐)
  22.                         sub        rsp, 28h

  23.                         ;计算参数个数是否超过4个, (没超过 4个, 则直接跳转FUN2快速传参)
  24.                         mov        eax, r8d
  25.                         cmp        eax, 5
  26.                         ;小于5个参数直接跳转 FUN2快速传参
  27.                         jb        FUN2

  28.                         ;如果是超过4个参数的情况(计算出 传参数组的 尾指针的 后一指针)
  29.                         lea        rbx, [rdx + r8 *8h]

  30.                         ;将超过4个参数的 剩余参数 入栈
  31.                         LOOP1:
  32.                                 ;arr 前移
  33.                                 sub        rbx, 8h

  34.                                 ;参数倒序入栈
  35.                                 mov        rax, qword ptr [rbx]  
  36.                                 push        rax               

  37.                                 ;不相等则继续压参
  38.                                 cmp        rbx, rdx
  39.                                 jnz        LOOP1               

  40.                         ;复制参数数目, 以便之后比较
  41.                         mov        eax, r8d

  42.                 FUN2:
  43.                         ;复制传参数组指针
  44.                         mov rbx, qword ptr [rdi + 20h]

  45.                         ;如果是无参数函数
  46.                         cmp        eax, 0
  47.                         je        FUN1

  48.                         ;如果是1个参数
  49.                         mov        rcx,qword ptr [rbx + 0h]  
  50.                         cmp        eax, 1
  51.                         je FUN1

  52.                         ;如果是2个参数
  53.                         mov        rdx,qword ptr [rbx + 8h]
  54.                         cmp        eax, 2
  55.                         je FUN1

  56.                         ;如果是3个参数
  57.                         mov        r8, qword ptr [rbx + 10h]
  58.                         cmp        eax, 3
  59.                         je FUN1

  60.                         ;如果是4个参数
  61.                         mov        r9, qword ptr [rbx + 18h]

  62.                 FUN1:
  63.                         ;调用dll中的函数
  64.                         mov     rbx, qword ptr [rdi + 18h]
  65.                         call    rbx

  66.                         ;获取返回模式参数
  67.                         mov     rbx, qword ptr [rdi + 30h]
  68.                         ;如果返回模式为真, 输出整型指针
  69.                         cmp     rbx, 1
  70.                         je      FUNINT

  71.                         ;复制浮点数的运算结果
  72.                         movsd       mmword ptr [rsp+20h], xmm0
  73.                         jmp      FUN0

  74.                 FUNINT:
  75.                         ;复制整数的运算结果
  76.                         mov         qword ptr  [rsp+20h], rax


  77.                 FUN0:
  78.                         ;返回运算结果的指针
  79.                         mov         rax,  qword ptr [rsp+20h]  
  80.                         ;恢复栈指针
  81.                         mov        rsp, rdi
  82.                         ;寄存器原始值出栈
  83.                         pop        rbx
  84.                         pop        rdi  


  85.                         ret  

  86.                 FunCall64 ENDP
  87.                 END
  88.         */
  89. #else
  90. _int64  FunCall32( void* hProc, intptr_t* DLLParam, int DLLParamNum, int needINT )
  91. {
  92.         union
  93.         {
  94.                 _int64  retInt64;
  95.                 int     retInt[2];
  96.         } RetInt;
  97.         // 返回值容器清零
  98.         RetInt.retInt64 = 0;

  99.         // ESP备份容器, 实现兼容调用stdcall 和 cdecl
  100.         int bakESP = 0;

  101.         // 使用内联汇编, 低效稳定
  102.     __asm
  103.     {
  104.                 ;备份栈帧
  105.                 mov bakESP,        esp

  106.                 ;获取输入的参数
  107.         mov                ebx, dword ptr [DLLParam]
  108.         mov                ecx, dword ptr [DLLParamNum]
  109.         dec                ecx
  110.                 ;计算出 传参数组 末尾指针
  111.                 lea                ebx, [ebx + ecx *4h]


  112.         CYC:
  113.                 ;倒序 取出参数
  114.                 mov                eax, dword ptr [ebx]
  115.                 ;参数 指针前移
  116.                 sub                ebx, 4
  117.                 ;压栈
  118.                 push        eax
  119.                 dec                ecx
  120.                 ; 不为负值,则参数循环压栈
  121.                 jns                CYC               

  122.                 ;调用函数, 执行call过程
  123.         call dword ptr [hProc]

  124.                 ;如果返回模式为真, 输出整型指针
  125.                 mov                ecx, dword ptr [needINT]
  126.                 cmp     ecx, 1
  127.                 je      FUNINT
  128.                 ;返回浮点值
  129.         fstp        RetInt.retInt64;
  130.                 jmp                FUNEND

  131.         FUNINT:
  132.         mov                RetInt.retInt[0], eax

  133.         FUNEND:
  134.                 ;针对 _cdecl 类型函数的call,由上级调用函数也就是FunCall32 负责 清理堆栈
  135.                 ;恢复栈帧
  136.                 mov                esp,        bakESP
  137.     }

  138.         // 返回结果
  139.         return (RetInt.retInt64);
  140. }
  141. #endif
复制代码

评分

参与人数 2PB +26 技术 +1 收起 理由
netbenton + 20 + 1 我怎么会错过这么好的帖子呢?
老刘1号 + 6 青回系列

查看全部评分

发表于 2021-9-26 06:16:27 | 显示全部楼层
本帖最后由 peterboy666 于 2021-9-26 06:22 编辑

http://www.bathome.net/thread-43259-1-1.html

试了一些例子 无法操作
不兼容吗 ?

F:\SEP_TempPass\1>icmd64.exe icmd64.dll

F:\SEP_TempPass\1>set /i a=1+2
命令語法不正確。

F:\SEP_TempPass\1>set /i a=sin(torad(30)+cos(tan(3)))/7*6+exp(5)
命令語法不正確。

-----------------------------------------------------------------------------
常数类
        pi    3.1415926535897932
        e     2.7182818284590452      

通用类
        rand  随机数
        round 四舍五入
        int   取整
        ceil  向上舍入
        floor 向下舍入
        abs   绝对值
        sqrt  开方
        lg    常用对数,以10为底
        ln    自然对数
        exp   e的次幂
        gamma 伽玛函数
        deg   度转弧度
        +     加
        -     减
        *     乘
        /     除
        %     取余数
        ^     次方
        !     阶乘

三角函数类
        sin、cos、tan   
        arcsin、arccos、arctan

双曲函数类
        sinh、cosh、tanh
        arcsinh、arccosh、arctanh
-----------------------------------------------------------------------------

评分

参与人数 1PB +10 技术 +1 收起 理由
netbenton + 10 + 1 我怎么会错过这么好的帖子呢?

查看全部评分

 楼主| 发表于 2021-9-27 00:50:05 | 显示全部楼层
回复 2# peterboy666
科学计算需要下载科学计算库dll,才能调用, 就是这个是调用外部 dll, 来实现各种功能, 那个科学计算的版本以前传过, 不过文件已经过期了,你也下载不到了.
发表于 2021-9-27 01:41:16 | 显示全部楼层
回复 3# slimay

理解 谢谢.

CMD 的多年缺点 就是 只有整数 且 整数小于 2GB
假如你的 ICMD 能结合 科学计算库 就更好了.

看你的批处理 只有 ICMD64

C:\> ICMD64
C:\> ICMD64 ICMD64.DLL
两者有何不同 ?
发表于 2021-9-27 01:49:30 | 显示全部楼层
本帖最后由 peterboy666 于 2021-9-27 01:52 编辑

一般 CMD 有 [/C | /K] string] 参数,
ICMD 如有 /C 更方便使用

例:
C:\>icmd64 /c set *a=MessageBoxW 0 L"test" L"title" 1 & echo %a%

让 ICMD 去处理一些事,
把结果回传给批.
 楼主| 发表于 2021-9-28 14:24:29 | 显示全部楼层
本帖最后由 slimay 于 2021-9-28 14:26 编辑

回复 5# peterboy666
icmd一直都是把结果传回给批的,在返回值里, 这个外置版, 可以方便你自己写dll库,调用自己的库, 或者其他第三方库, 比如image.dll
下载地址: http://cmd1152.ys168.com/  文件区  icmd 1.1扩展版.zip (增加16进制参数支持, 增加外置计算器库calc函数)
请下载 最新 扩展板,  支持小数运算,使用了外置库calc,示例如下:
  1. @REM 先设置工作目录,添加路径icmd_home
  2. @set "PATH=%PATH%;%~DP0\icmd_home"

  3. @REM 启用icmd64仅用于64位WIN系统, 且能调用64位DLL
  4. @icmd64

  5. @REM 一次载入全部的扩展DLL文件, 省的每次呼叫
  6. @set *= iload  L"calc.dll" ^
  7.                L"user32.dll"    ^
  8.                L"kernel32.dll"  ^
  9.                L"gdi32.dll"     ^
  10.                L"gdiplus.dll"   ^
  11.                L"msvcrt.dll"


  12. @echo off
  13. set ~a= calc A"sin(torad(30)+cos(tan(3)))/7*6+exp(5)"
  14. echo %a%
  15. pause
复制代码
发表于 2021-9-29 15:49:21 | 显示全部楼层
可以说是最强命令行扩展了,大佬可以考虑一下把 repo 托管到网站上吗。
发表于 2021-9-29 16:11:59 | 显示全部楼层
回复 6# slimay

>请下载 最新 扩展板,  支持小数运算,使用了外置库calc,示例如下

實測很好用,
發展下去,
一遍光明.

小缺點:

1.
set ~a= calc A"3*pi+sin(pi/6)"

計算 9.924777960
實測 9.433916356

誤差 0.5 很大

2.
set ~a= calc A"2^64"

計算 1.84467440737E+019
MS Calc.exe 18446744073709551616 這種比較好
 楼主| 发表于 2021-9-29 17:52:59 | 显示全部楼层
本帖最后由 slimay 于 2021-9-29 18:27 编辑

回复 7# Byaidu
好的, image老大
这个使用了一个hash桶技巧, 就是对调用过的函数都把函数地址存入了hash桶缓存, 下次调用直接取函数地址,非常快, 不需要每次都GetAddress, 也不需要知道函数是哪个dll里的, 一次把想载入的dll都载入.这个hash桶的深度只有16层, 但是却解决了高速循环调用函数的问题, 它是桶循环, 就是优先会把之前call过的函数缓存起来, 如果再次调用, 直接取函数地址调用, 速度可能会比capi节省1秒左右吧.
 楼主| 发表于 2021-9-29 17:57:22 | 显示全部楼层
本帖最后由 slimay 于 2021-9-29 18:03 编辑

回复 8# peterboy666
3*pi+sin(pi/6) 没有计算错, 因为一般是按弧度值计算sin的, 你可能科学计算器没有切换成弧度制吧.   π/6 六分之派就是 30度, sin30度就是0.5 加上前面3个派 9.9是正确的,弧度制下.还有高精度需要cpu的支持, 默认浮点数就只有16位精度, 如果需要更多的精度, 需要模拟高精度运算, 那样计算速度会很慢.微软的计算器就是模拟的高精度计算, 它只能计算少量的算是高精度. 但是icmd是用于批处理, 为了保证运行速度, 只能暂时才用最多16位精度, 精度太高了, 运行速度明显会慢很多, 因为批处理要循环做一些事情, 不适合高精度计算.
...
如果要做大数运算, 你可以直接把python的dll复制到icmd_home目录, 直接调用python的eval函数搞定大数运算
就是icmd是个万能接口, 几乎可以呼叫各种dll., 32位64位dll的函数都能调用, 理论上你要的功能可以通过复制调用别的软件的dll里的函数实现.所以icmd本身也不需要做大数运算支持, 因为gmp库的dll已经有很多大数运算函数,好多dll都有大数运算的函数可供你调用.放到icmd_home目录里就能调用.完全可行.
发表于 2021-9-29 19:45:40 | 显示全部楼层
理解.

不过现在 PC 效能,
MS Calc.exe 都是不到 1 秒就秒解.

其它就靠万能接口去处理 ICMD 的不足了.
 楼主| 发表于 2021-9-29 20:16:04 | 显示全部楼层
本帖最后由 slimay 于 2021-9-29 20:20 编辑

回复 11# peterboy666
嗯, 因为是批处理, 不能直接用大数计算, 否则,很多批处理的基础功能也会受到影响, 甚至得出不正确的结果. 批处理只是处理2G范围的数, 所以为了兼容批处理的其他功能, 这个icmd最好还是只支持2G运算比较安全. 太大的数, 可以直接调用大数计算库, gmp库, 你可以网上下载gmp.dll直接供icmd呼叫,我以前上传过大数库gmp库,在csdn上, 不过你需要积分才能下载.

不过icmd已经非常强大了, 直接就能代替批处理的很多功能, 因为有很多dll,里边的函数足够你完成很多工作和任务.
发表于 2021-9-29 22:17:51 | 显示全部楼层
回复 12# slimay


    我之前直接丢给 PowerShell 算,再丢回给批.
 楼主| 发表于 2021-9-29 22:19:22 | 显示全部楼层
本帖最后由 slimay 于 2021-9-29 22:20 编辑

回复 13# peterboy666
哦,现在只要找到需要的功能dll, 就能直接调用批处理, 不再需要ps传值了. 对了另外icmd可以直接调用 ps的dll, 内嵌powershell和com
发表于 2021-9-29 22:34:46 | 显示全部楼层
回复 14# slimay


基本上 PowerShell 也是个万能宝库,
批搞不定的就丢给 PowerShell 搞.

ICMD 是很强大,
但它不是 OS 内置,
另一点它的作法很敏感,
我使用的 Symantec Endpoint Protection 全部报警,
沽计其它防毒软件也会报警.
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|批处理之家 ( 渝ICP备10000708号 )

GMT+8, 2026-3-17 02:50 , Processed in 0.015539 second(s), 9 queries , File On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表