吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2033|回复: 3
收起左侧

[其他转载] C++ x86/x64 内联汇编 MsgBox 以及 printf 返回值

[复制链接]
Vvvvvoid 发表于 2022-6-5 15:17
本帖最后由 Vvvvvoid 于 2022-7-26 00:40 编辑

VS 编译 x64 ASM 下配置 (x86 不需要)

  1. Command line : ml64 /Fo $(IntDir)%(fileName).obj /c %(fileName).asm   

  2. Output : $(IntDir)%(fileName).obj

函数描述
MessageBoxA

user32 下的信息框函数 , 四个参数分别为 :
HWND hWnd, // 窗口句柄
LPCSTR lpText, // 标题
LPCSTR lpCaption, // 内容
UINT uType //按钮类型, 如果为0的话,函数返回值固定为1

printf

C语言标准库函数,是指格式化输出函数
参数1: 格式化的字符串
参数2: 替换的变量

eg: printf ("hello %s"","world");  // 控制台输出 hello world

代码实现

char* title = "this is title"; // 通用 msgbox 标题
char* val = "this is val"; // 通用 msgbox 内容
// 调用 msgbox 会返回eax值,这里在继续调用 printf 函数输出返回值
char* asm_print_format = "asm_ret_resut : %p\n";
// 获取msgbox 函数地址
DWORD_PTR lpAddr = (DWORD_PTR)GetProcAddress(GetModuleHandle("user32.dll"), "MessageBoxA");
// LOG_INFO 是我自己封装的控制台输出,这里我就注释掉了, 自行打印吧
// LOG_INFO("user32.dll:MessageBoxA addr is -> %p", lpAddr);
// LOG_INFO("printf addr is -> %p", &printf);
// printf("fuckyou %p",0x123); // 这里自己掉用了下 printf 函数, 方便下断观察参数调试

#if defined(_M_X64) 
      // x64 需要单独创建 asm 文件(如下)来支持内联汇编
      asm_msg_box_x64(title, val, lpAddr, asm_print_format);

#else
      // x86 asm
      __asm {
            // 第一个 call调用 msgbox
            push 0;
            push title;
            push val;
            push 0;
            call lpAddr;

            // 第二个call,这里eax 为 msgbox 返回值
            push eax;
            push asm_print_format;
            call printf;
            // 堆栈平衡, add esp 4*n, n为参数数量
            add esp, 0x8;
      }
#endif
_msg_box.asm (x64)

extrn printf: proc ; 
extrn MessageBoxA: proc ; 

.data
.CODE  ;

asm_msg_box_x64 PROC  ;

    push rbp
    sub rsp,30h ; // 这里的 30h与 add rsp 对应, 进⼊call之前rsp必须要满⾜0x10 (16)字节对齐,可自行加减8调节 eg(38h)

    mov         qword ptr [rsp+20h],r9
    mov         qword ptr [rsp+18h],r8
    mov         qword ptr [rsp+10h],rdx
    mov         qword ptr [rsp+8],rcx

    mov r9,0
    mov r8, [rsp+8]
    mov rdx, [rsp+10h]
    mov rcx,0
    call qword ptr [rsp+18h] ; // 这里我们是将 msgbox 地址通过变量传递过来了, 也可以在该文件extrn MessageBoxA, 然后直接 call MessageBoxA, 改函数返回值会放到寄存器 rax中

    mov rcx,[rsp+20h] ; // x64, 默认前四个参数由 rcx,rdx,r8,r9 四个寄存器传参,printf 俩个参数, 所以用到了 rcx,rdx
    mov rdx,rax
    // x64 的堆栈平衡全依赖外部的 sub/add esp , 没有call内部的 ret xx 这个约定了
    call printf

    add rsp,30h ; 
    pop rbp
    ret

asm_msg_box_x64 ENDP  ;

END     ;

关于堆栈保护

查了一些资料, 要使用内联汇编, 只要不是_declspec(naked)修饰的话 , 编译器会自动为我们写入一些保护指令,
所以这里 不需要在 push rax, push rbx...  pop rbx pop rax 来保存恢复堆栈 ,
当然如果是远程注入的话 还是需要保护下的.
x86/x64 远程注入 参考  https://www.52pojie.cn/thread-1504396-1-1.html



out.jpg

免费评分

参与人数 3吾爱币 +9 热心值 +3 收起 理由
笙若 + 1 + 1 谢谢@Thanks!
gunxsword + 1 + 1 热心回复!
苏紫方璇 + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

Niko999 发表于 2022-6-5 15:27
收藏一下,多出点教程哥哥
hackerbob 发表于 2022-6-5 17:17
用push压栈时,直接压指针不就行了吗,为啥还要存到eax寄存器,把eax寄存器压进去?

免费评分

参与人数 1吾爱币 +2 热心值 +1 收起 理由
Vvvvvoid + 2 + 1 被 x64 的 mov 整迷糊了, 已修复

查看全部评分

 楼主| Vvvvvoid 发表于 2022-6-5 17:41
本帖最后由 Vvvvvoid 于 2022-6-5 17:47 编辑
hackerbob 发表于 2022-6-5 17:17
用push压栈时,直接压指针不就行了吗,为啥还要存到eax寄存器,把eax寄存器压进去?

写迷糊了, 已修复 .  
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-25 05:51

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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