内联汇编是C/C++的一个重要特性,内联汇编顾名思义是可以在C/C++ 语法内嵌套使用汇编指令,使用内联汇编的好处就是可以更灵活便捷,我觉得尤其是在做逆向这一块,简直不要太爽。
内联汇编Demo:
#include
#include
int asmFunc()
{
int a = 0;
__asm
{
// 变量a 地址复制给eax
mov eax, a
// eax 地址做加点运算
add eax, 0x1213
// 将计算后的值传递a
mov a, eax
}
// 返回eax
return a;
}
int main()
{
printf("0x%X\r\n", asmFunc());
system("pause");
}
以上是32 位C/C++ 使用内联汇编的小Demo,在x32 开发中,使用__asm 关键字就可以在其代码块内嵌入x32 汇编代码,好不方便。但是突然发现,x64 开发中,不支持这种内联汇编,尴尴尬尬,那我要是逆向一个x64 程序的时候怎么调用CALL(其实可以使用函数指针),而且也不灵活,不方便呀。好在有属于x64 的“内联汇编”
接下来,可以写入汇编指令
注:
汇编格式
.CODE ;这是开始
; 这是注释(; + 注释内容)
; 这是方法名称
funcName PROC
;这里写入汇编指令
funcName ENDP
END ;这是结束
x64 汇编传递参数
64 位程序传递参数仅使用__fastcall 约定,及前4个参数由寄存器rcx, rdx, r8, r9传递,其他使用堆栈传递。详细;fastcall
与高级语言开发类似,函数名称不要使用指令名称,如add, test, mov
.CODE
myAdd PROC
sub rsp, 20h
xor rax, rax
add rax, rcx
add rax, rdx
add rax, r8
add rax, r9
add rax, [rsp + 50h]
add rax, [rsp + 48h]
add rsp, 20h
ret
myAdd ENDP
END
#include
#include
// 使用C 的方式
EXTERN_C UINT64 myAdd(UINT64 arg1, UINT64 arg2, UINT64 arg3, UINT64 arg4, UINT64 arg5, UINT64 arg6);
int main()
{
Sleep(1);
printf("%d\r\n", myAdd(1, 1, 1, 1, 1, 1));
Sleep(1);
system("pause");
}
这里我说一下我的思路,之前x64 程序我调用call 都是使用函数指针来调用,这种方式虽然可以很方便的调用call,但是无奈不灵活(也可能是因为我太太太太太太太太太太菜)只能去使用已有的功能,所以这次使用汇编调用call,实现功能的修改,以下所有程序都是自写测试用:
#include
#include
#include
int add(int a, int b)
{
printf("test Msg\r\n");
return a + b;
}
int main()
{
Sleep(1);
printf("结果 = %d\r\n", add(1, 555));
Sleep(1);
system("pause");
return 0;
}
#include
#include
#define DLL_PATH "D:\\c_work\\x64远程调用CALL_汇编测试\\x64\\bin\\Dll.dll"
#define TAR_PROCESS_CLASS "ConsoleWindowClass"
#define TAR_PROCESS_TITLE "D:\\c_work\\x64远程调用CALL_汇编测试\\x64\\bin\\TarProject.exe"
int main()
{
// 获取PID
DWORD pId = 0;
HWND hWnd = FindWindowA(TAR_PROCESS_CLASS, TAR_PROCESS_TITLE);
GetWindowThreadProcessId(hWnd, &pId);
// 打开进程
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pId);
// 开辟内存
LPWORD lpAddr = (LPWORD)VirtualAllocEx(hProcess, NULL, 250, MEM_COMMIT, PAGE_READWRITE);
// 写入DLL 全路径
char path[256] = { 0 };
strcpy(path, DLL_PATH);
WriteProcessMemory(hProcess, lpAddr, path, strlen(path) + 1, 0);
CreateRemoteThread(hProcess,
NULL,
NULL,
(LPTHREAD_START_ROUTINE)LoadLibraryA,
lpAddr,
NULL,
NULL);
}
3.1. ASM
.code
testAsmFunc PROC
;000000014000 | BA 2B020000 | mov edx,22B | maintest.cpp:14
;000000014000 | B9 01000000 | mov ecx,1 |
;000000014000 | E8 B2FFFFFF | call
3.2 CPP
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
#include "stdio.h"
#include "windows.h"
extern "C" UINT64 testFunc(int a, int b);
extern "C" UINT64 testAsmFunc();
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
// 加载
int value = testAsmFunc();
char szpValue[256] = { 0 };
sprintf(szpValue, "%d", value);
MessageBox(NULL, szpValue, szpValue, MB_OK);
}; break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
github 地址:https://github.com/JiaJinRong12138/TestAsmX64.git