本帖最后由 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);
- }
- #endif
复制代码
|