VS2022 Windows X64 下C/C++与汇编(asm)混写并且调用lib学习笔记
前言
之前学习了liunx
下的shellcode
,之后分析了Windows
下msf
的shellcode
汇编实现,然后听了队内逆向大佬讲的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
(下文简称vs2020
和vs
)
主要的工作负债如图
新建的时候选择控制台(其实选什么没什么关系,你愿意写gui马可以选gui)
跟着添加
直接输入fyn.asm
,命名按照自己喜好即可
跟着选
选择
接下来设置(注意是在哪里右键)
二、写代码
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.cpp
里include
后仍然要导入一遍。
检查一个lib导出了什么的命令,请记得在VS2020控制台内打开
方法一:
方法二:
可以看到导出了什么东西
dumpbin /exports C:\Windows\System32\ucrtbase.dll
2.3 .data
.data
fmt db "Text from C:1111", 10, 0 ; "%s\n"
fmt
理解为变量名字,可以随便取db
是define 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 proc
和asm_func endp
前面是函数名,后面是标识开始和结束,这个函数名要和main.cpp
里的一致(就是要一起改)
可以定义多个函数,在end
前面可以定义多个xxxx endp
和xxxx proc
2.5 end
提示结束
运行直接run即可
总结
这种方法的优点是不用从头写,本体既是加载器,方便嵌入其中,有很多妙妙操作也可以实现(比方说手动实现printf
里面藏一点好东西之类的),缺点也很明显,过度依赖vs2022,迁移性很差。