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

[其他] ICMD64版32版发布

本帖最后由 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
复制代码
2

评分人数

本帖最后由 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
-----------------------------------------------------------------------------
1

评分人数

    • netbenton: 我怎么会错过这么好的帖子呢?PB + 10 技术 + 1

TOP

回复 2# peterboy666
科学计算需要下载科学计算库dll,才能调用, 就是这个是调用外部 dll, 来实现各种功能, 那个科学计算的版本以前传过, 不过文件已经过期了,你也下载不到了.

TOP

回复 3# slimay

理解 谢谢.

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

看你的批处理 只有 ICMD64

C:\> ICMD64
C:\> ICMD64 ICMD64.DLL
两者有何不同 ?

TOP

本帖最后由 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 去处理一些事,
把结果回传给批.

TOP

本帖最后由 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
复制代码

TOP

可以说是最强命令行扩展了,大佬可以考虑一下把 repo 托管到网站上吗。

TOP

回复 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 這種比較好

TOP

本帖最后由 slimay 于 2021-9-29 18:27 编辑

回复 7# Byaidu
好的, image老大
这个使用了一个hash桶技巧, 就是对调用过的函数都把函数地址存入了hash桶缓存, 下次调用直接取函数地址,非常快, 不需要每次都GetAddress, 也不需要知道函数是哪个dll里的, 一次把想载入的dll都载入.这个hash桶的深度只有16层, 但是却解决了高速循环调用函数的问题, 它是桶循环, 就是优先会把之前call过的函数缓存起来, 如果再次调用, 直接取函数地址调用, 速度可能会比capi节省1秒左右吧.

TOP

本帖最后由 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目录里就能调用.完全可行.

TOP

理解.

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

其它就靠万能接口去处理 ICMD 的不足了.

TOP

本帖最后由 slimay 于 2021-9-29 20:20 编辑

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

不过icmd已经非常强大了, 直接就能代替批处理的很多功能, 因为有很多dll,里边的函数足够你完成很多工作和任务.

TOP

回复 12# slimay


    我之前直接丢给 PowerShell 算,再丢回给批.

TOP

本帖最后由 slimay 于 2021-9-29 22:20 编辑

回复 13# peterboy666
哦,现在只要找到需要的功能dll, 就能直接调用批处理, 不再需要ps传值了. 对了另外icmd可以直接调用 ps的dll, 内嵌powershell和com

TOP

回复 14# slimay


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

ICMD 是很强大,
但它不是 OS 内置,
另一点它的作法很敏感,
我使用的 Symantec Endpoint Protection 全部报警,
沽计其它防毒软件也会报警.

TOP

返回列表