返回列表 发帖

[其他] 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位汇编源码: (一直开源, 从不保留,方便他人研究,只因论坛限制字数, 只能贴这点最核心的了)
// FunCall 汇编函数
#ifdef  _WIN64
/*
;64位汇编 仅在单独的asm文件中方可编译, 不能内联
;intptr_t  FunCall64( void* hProc, intptr_t* DLLParam, int DLLParamNum, int needINT )
;CALL 64 APL, MADE BY SLIMAY 2021.09.24
.CODE
FunCall64 PROC
;  函数地址     传参数组     传参数目     传参模式
;intptr_t* hProc, void* DLLParam, int DLLParamNum, int needINT
;先备份传入的参数值
mov qword ptr [rsp +20h],  r9
mov qword ptr [rsp +18h],  r8  
mov qword ptr [rsp +10h],  rdx
mov qword ptr [rsp + 8h],  rcx
;寄存器原始值入栈
push rdi
push rbx
;栈指针备份
mov rdi, rsp
;设定快速传参栈空间(下移5个int64空间, 16字节对齐)
sub rsp, 28h
;计算参数个数是否超过4个, (没超过 4个, 则直接跳转FUN2快速传参)
mov eax, r8d
cmp eax, 5
;小于5个参数直接跳转 FUN2快速传参
jb FUN2
;如果是超过4个参数的情况(计算出 传参数组的 尾指针的 后一指针)
lea rbx, [rdx + r8 *8h]
;将超过4个参数的 剩余参数 入栈
LOOP1:
;arr 前移
sub rbx, 8h
;参数倒序入栈
mov rax, qword ptr [rbx]  
push rax
;不相等则继续压参
cmp rbx, rdx
jnz LOOP1               
;复制参数数目, 以便之后比较
mov eax, r8d
FUN2:
;复制传参数组指针
mov rbx, qword ptr [rdi + 20h]
;如果是无参数函数
cmp eax, 0
je FUN1
;如果是1个参数
mov rcx,qword ptr [rbx + 0h]  
cmp eax, 1
je FUN1
;如果是2个参数
mov rdx,qword ptr [rbx + 8h]
cmp eax, 2
je FUN1
;如果是3个参数
mov r8, qword ptr [rbx + 10h]
cmp eax, 3
je FUN1
;如果是4个参数
mov r9, qword ptr [rbx + 18h]
FUN1:
;调用dll中的函数
mov     rbx, qword ptr [rdi + 18h]
call    rbx
;获取返回模式参数
mov     rbx, qword ptr [rdi + 30h]
;如果返回模式为真, 输出整型指针
cmp     rbx, 1
je      FUNINT
;复制浮点数的运算结果
movsd       mmword ptr [rsp+20h], xmm0
jmp      FUN0
FUNINT:
;复制整数的运算结果
mov         qword ptr  [rsp+20h], rax
FUN0:
;返回运算结果的指针
mov         rax,  qword ptr [rsp+20h]  
;恢复栈指针
mov rsp, rdi
;寄存器原始值出栈
pop rbx
pop rdi  
ret  
FunCall64 ENDP
END
*/
#else
_int64  FunCall32( void* hProc, intptr_t* DLLParam, int DLLParamNum, int needINT )
{
union
{
_int64  retInt64;
int     retInt[2];
} RetInt;
// 返回值容器清零
RetInt.retInt64 = 0;
// ESP备份容器, 实现兼容调用stdcall 和 cdecl
int bakESP = 0;
// 使用内联汇编, 低效稳定
    __asm
    {
;备份栈帧
mov bakESP, esp
;获取输入的参数
        mov ebx, dword ptr [DLLParam]
        mov ecx, dword ptr [DLLParamNum]
        dec ecx
;计算出 传参数组 末尾指针
lea ebx, [ebx + ecx *4h]
CYC:
;倒序 取出参数
mov eax, dword ptr [ebx]
;参数 指针前移
sub ebx, 4
;压栈
push eax
dec ecx
; 不为负值,则参数循环压栈
jns CYC               
;调用函数, 执行call过程
        call dword ptr [hProc]
;如果返回模式为真, 输出整型指针
mov ecx, dword ptr [needINT]
cmp     ecx, 1
je      FUNINT
;返回浮点值
        fstp RetInt.retInt64;
jmp FUNEND
FUNINT:
        mov RetInt.retInt[0], eax
FUNEND:
;针对 _cdecl 类型函数的call,由上级调用函数也就是FunCall32 负责 清理堆栈
;恢复栈帧
mov esp, bakESP
    }
// 返回结果
return (RetInt.retInt64);
}
#endifCOPY
2

评分人数

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

TOP

本帖最后由 slimay 于 2021-9-28 14:26 编辑

回复 5# peterboy666
icmd一直都是把结果传回给批的,在返回值里, 这个外置版, 可以方便你自己写dll库,调用自己的库, 或者其他第三方库, 比如image.dll
下载地址: http://cmd1152.ys168.com/  文件区  icmd 1.1扩展版.zip (增加16进制参数支持, 增加外置计算器库calc函数)
请下载 最新 扩展板,  支持小数运算,使用了外置库calc,示例如下:
@REM 先设置工作目录,添加路径icmd_home
@set "PATH=%PATH%;%~DP0\icmd_home"
@REM 启用icmd64仅用于64位WIN系统, 且能调用64位DLL
@icmd64
@REM 一次载入全部的扩展DLL文件, 省的每次呼叫
@set *= iload  L"calc.dll" ^
               L"user32.dll"    ^
               L"kernel32.dll"  ^
               L"gdi32.dll"     ^
               L"gdiplus.dll"   ^
               L"msvcrt.dll"
@echo off
set ~a= calc A"sin(torad(30)+cos(tan(3)))/7*6+exp(5)"
echo %a%
pauseCOPY

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

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

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

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

TOP

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

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

TOP

回复 15# peterboy666
是的, 360也会警告的,毕竟是注入版, 要修改cmd的内存, 一些防护软件是会拦截这种修改C盘系统程序的 行为的.,属于正常现象.

TOP

TOP

返回列表