VS2022 Windows X64 下C/C++与汇编(asm)混写并且调用lib学习笔记

前言

之前学习了liunx下的shellcode,之后分析了Windowsmsfshellcode汇编实现,然后听了队内逆向大佬讲的x86内联汇编以及各种利用方法,于是思考能不能用x64写汇编,踩了很多坑,于是写此文记录学习过程。

前置天赋点:

  • C/C++
  • AMD64 汇编(下文简称asm
  • ctf二进制

参考:
https://bbs.huoban.com/thread-5667-1-1.html
https://www.cnblogs.com/AD-milk/p/13711369.html

一、环境搭建

1.1 Visual Studio 2022(下文简称vs2020vs

主要的工作负债如图

img

新建的时候选择控制台(其实选什么没什么关系,你愿意写gui马可以选gui)
img

跟着添加
img

直接输入fyn.asm,命名按照自己喜好即可
img

跟着选
img

选择
img

接下来设置(注意是在哪里右键)
img

二、写代码

2.1 main.cpp

在主要的文件中写:

#include <stdio.h>

extern "C" void __stdcall asm_func();

int main() {
    asm_func();
    return 0;
}

解释:

  • extern "C" : 使用C函数形式调用外部函数
  • __stdcall : 由外部函数控制扩展和清理栈

至于函数名按需要取

2.2 fun.asm

includelib ucrt.lib
includelib legacy_stdio_definitions.lib

.data
    fmt db "Text from C:1111", 10, 0      ; "\n"

.code
align 16

;Function prototypes 
printf PROTO  arg1:PTR byte

asm_func proc
    sub rsp, 28h; Shadow space (32字节) + 保证16字节对齐
    mov r10, rcx
    lea rcx, fmt; 第1个参数: format string
    call printf

    add rsp, 28h
    ret
asm_func endp

end

这里讲究的比较多

2.2.1 includelib

  • includelib ucrt.lib
  • includelib legacy_stdio_definitions.lib

这两条指令是导入lib供下文使用(例如printf),具体要用什么函数就要导入对应的lib,理论上导入ucrt.lib就可以了,但是微软在VS 2017后分离了一些经典的输入输出导出表到别的地方,但是微软为了兼容又在legacy_stdio_definitions.lib将它们再次导出了,所以可以用了。

注意这里如果在main.cppinclude后仍然要导入一遍。

检查一个lib导出了什么的命令,请记得在VS2020控制台内打开

方法一:
img

方法二:
img

可以看到导出了什么东西
img

dumpbin /exports C:\Windows\System32\ucrtbase.dll

2.3 .data

.data
    fmt db "Text from C:1111", 10, 0      ; "%s\n"
  • fmt 理解为变量名字,可以随便取
  • dbdefine byte的缩写,表示定义一个或多个字节(byte)常用于定义字符串、字符、字节数据等。每个字符会被翻译成一个字节(ASCII 编码)
  • "Text from C:1111", 10, 0 的意思是 Text from C:1111 + \n + \0 (ASCII 编码)

把用到的字符串和数据丢到这里即可,当然,在下文手动组装也可以

2.4 .code

.code
align 16

;Function prototypes 
printf PROTO  arg1:PTR byte

asm_func proc
    sub rsp, 28h            ; Shadow space (32字节) + 保证16字节对齐

    mov r10, rcx
    lea rcx, fmt            ; 第1个参数: format string
    call printf

    add rsp, 28h
    ret
asm_func endp
  • align 16 需要16位对齐(pwn手看到这个已经PTSD了)
  • printf PROTO arg1:PTR byte 声明函数以及变量位置、类型、数量(方便编译器检查罢了,可以不加,但是推荐加)
  • asm_func procasm_func endp 前面是函数名,后面是标识开始和结束,这个函数名要和main.cpp里的一致(就是要一起改)

可以定义多个函数,在end前面可以定义多个xxxx endpxxxx proc

2.5 end

提示结束

运行直接run即可
img

总结

这种方法的优点是不用从头写,本体既是加载器,方便嵌入其中,有很多妙妙操作也可以实现(比方说手动实现printf里面藏一点好东西之类的),缺点也很明显,过度依赖vs2022,迁移性很差。

posted @ 2025-05-24 16:22  归海言诺  阅读(1203)  评论(0)    收藏  举报